我正在创建一个应用程序,允许用户定义不同形状的尺寸,并使用他们指定的尺寸将区域返回给用户。
我的基类是Shape。派生类是三角形,圆形,正方形和矩形。
我创建了一个Shape数组,希望在运行时在数组中创建和存储任何派生类的实例。
Shape** shape = new Shape*[TOTAL_SHAPES];
shape[i] = new Circle(radius);
我已经管理了这个,但是我无法访问实例化的类方法。对不起,如果这是一个愚蠢的问题,我对C ++还不熟悉。
答案 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)
您有三种选择:
Shape
成为一个抽象基类,并调用virtual
Shape
方法
static_cast
从Shape*
投射到Circle*
,并通过该方法调用方法。dynamic_cast
从Shape*
投射到Circle*
,并通过该方法调用方法。在许多情况下,第一种选择可能是最好的。除了其他原因之外,你几乎肯定需要一个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
。