基类的C++数组,该数组的元素中存储有派生类的实例

C++ array of base class which has instances of derived classes stored in the elements of the array

本文关键字:数组 派生 存储 实例 元素 C++ 基类      更新时间:2023-10-16

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

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

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

Shape** shape = new Shape*[TOTAL_SHAPES];
shape[i] = new Circle(radius);

我已经做到了,但是我无法访问实例化的类方法。很抱歉,如果这是一个愚蠢的问题,我对C++还很陌生。

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

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

有了这个定义,您可以通过执行以下来访问Shape上的方法

shape[i]->Method1();

然而,在这种情况下,不可能访问Method2,因为编译器只知道Shape,而不知道Circle

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

您有三个选项:

  1. Shape设为抽象基类,并调用作为Shape成员的virtual方法
  2. 使用static_castShape*强制转换为Circle*,并通过它调用方法
  3. 使用dynamic_castShape*强制转换为Circle*,并通过它调用方法

在许多情况下,第一个选项可能是最好的。除其他原因外,你几乎肯定需要一个virtual析构函数(这可能是使Shape成为ABC的副产品),而且你可能不想知道指向的对象是什么类型,而是想简单地调用它可能是什么的方法。如果你能用这个习惯用法,就用它吧。

第二种选择是危险的。您必须绝对知道要指向的对象是Circle(或其他任何对象)才能使用static_cast,否则您将得到Undefined Behavior。

第三个选项只有当您的类是多态时才可用,这意味着Shape必须至少有一个virtual方法。你当然应该有一个virtual析构函数,这将达到这个目的。

怎么样:

shape[i]->aMethod();

对于初学者,我强烈建议使用智能指针包装器,而不是使用原始指针(尤其是如果您是该语言的新手)。

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