基类的C ++数组,其中包含存储在数组元素中的派生类的实例

时间:2014-01-03 20:23:56

标签: c++ arrays inheritance base-class

我正在创建一个应用程序,允许用户定义不同形状的尺寸,并使用他们指定的尺寸将区域返回给用户。

我的基类是Shape。派生类是三角形,圆形,正方形和矩形。

我创建了一个Shape数组,希望在运行时在数组中创建和存储任何派生类的实例。

Shape** shape = new Shape*[TOTAL_SHAPES];

shape[i] = new Circle(radius);

我已经管理了这个,但是我无法访问实例化的类方法。对不起,如果这是一个愚蠢的问题,我对C ++还不熟悉。

4 个答案:

答案 0 :(得分:3)

我们假设您的类型具有以下定义

class Shape {
public:
  void Method1() { ... } 
};

class Circle : public Shape { 
  void Method2() { ... }
}

使用此定义,您可以通过执行以下操作来访问Shape上的方法

shape[i]->Method1();

在此上下文中虽然无法访问Method2,但因为编译器只知道Shape,而不是Circle

shape[i]->Method2(); // Error! 

答案 1 :(得分:1)

您有三种选择:

  1. 使Shape成为一个抽象基类,并调用virtual
  2. 成员的Shape方法
  3. 使用static_castShape*投射到Circle*,并通过该方法调用方法。
  4. 使用dynamic_castShape*投射到Circle*,并通过该方法调用方法。
  5. 在许多情况下,第一种选择可能是最好的。除了其他原因之外,你几乎肯定需要一个virtual析构函数(它可以是使Shape成为ABC的副产品),你可能更愿意不必知道什么类型的对象是被指出,而不是你想简单地调用方法。如果你可以使用这个习语,请使用它。

    第二种选择很危险。您必须绝对知道指向的对象是Circle(或其他)才能使用static_cast,否则您将获得未定义的行为。

    第三种选择只有在您的类是多态时才有可能,这意味着Shape 必须至少有一个virtual方法。你肯定应该有一个virtual析构函数,这就是为了这个目的。

答案 2 :(得分:0)

怎么样:

shape[i]->aMethod();

答案 3 :(得分:0)

对于初学者,我强烈建议使用智能指针包装器而不是使用原始指针(特别是如果您不熟悉该语言)。

std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);

这将定义一个初始大小为TOTAL_SHAPES的矢量。

对于问题的根源,您希望使用Shape*调用的任何方法必须对Shape有效,或者您必须对适当类型进行有风险的向下转换。例如:

class Shape
{
public:
    // constructors and other methods go here
    virtual ~Shape() { } // virtual destructor

    virtual void Draw() { } // virtual function to be used by derived classes
};

class Circle
{
public:
    // ...
    virtual ~Circle() { }
    virtual void Draw() { } // override the virtual function
};

然后,在您的应用程序代码中,

std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
shapes[0] = std::make_shared(new Circle);
shapes[0]->Draw(); // calls Circle::Draw

请注意,根据您的使用情况,std::unique_ptr可能会替换std::shared_ptr