以下问题对我来说有点难以制定,但请耐心等待,如果我能帮忙清除任何问题,请告诉我。
我正在为3D形状编写通用模拟。我正在使用基类:
class Shape{
public:
...
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
现在,由于我不知道用户将选择什么形状,因此我从中派生了几个类。 (例如:球体,立方体,四面体等)
到目前为止,一切都很好。 主要问题在于我有一个Controller类,它启动并运行模拟。作为私人成员,它应该有一个多个形状的矢量(所有相同的类型。例如:15个球体,或10个立方体等)。
class SimulationControl{
public:
void runsimulation();
private:
vector<Shape> all_shapes;
...
};
我想简单地使用非默认构造函数初始化此私有成员。 现在,在我知道自己做了什么之前,Eclipse已经告诉我“类型'Shape'必须实现继承的纯虚方法'Shape :: return_volume'”
我理解错误信息和错误,当然,但我仍然不明白如何解决它。
我希望能够做的是保持矢量类型未定义,然后在运行时通过构造函数创建它,并在运行时使用正确的派生类,当我知道用户选择了哪种类型的模拟时。 p>
以某种方式可以做到这一点吗?感谢
答案 0 :(得分:2)
使用(智能)指针。
你无法实例化一个抽象类,即使你可以,也可能不是你想要的,因为你将无法创建那些形状的别名。
您应该将SimulationControl
类的定义更改为更类似于此的内容(假设您的形状共享所有权 - 如果SimulationControl
是您的形状的唯一所有者,请使用{{1而不是unique_ptr
):
shared_ptr
然后,您可以创建形状的实例并将它们添加到#include <memory>
class SimulationControl {
public:
void runsimulation();
private:
std::vector<std::shared_ptr<Shape>> all_shapes;
...
};
集合中,如下所示(假设all_shapes
是从MyShape
派生的具体的,可默认构造的类):< / p>
Shape
答案 1 :(得分:2)
我不打算加入潮流并建议在容器中使用指针,无论是聪明还是愚蠢。这是使用PIMPL idiom的绝佳机会。
这个想法是该类只是实际实现的包装器,并在调用它时调用指向另一个对象的指针。包装器中包含的指针可以是多态的,这样它就可以实现它认为合适的函数。
class Shape{
public:
Shape() { pImpl = NULL; }
Shape(const Shape& from) { pImpl = from.pImpl->clone(); }
~Shape() { delete pImpl; }
Shape& operator=(const Shape& from) { pImpl = from.pImpl->clone(); }
...
double return_volume() { return pImpl->return_volume(); }
private:
ShapeImpl * pImpl;
...
};
class ShapeImpl{
public:
...
virtual ShapeImpl* clone() const =0;
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
因为Shape
类包含指针,所以需要实现rule of three并创建析构函数,复制构造函数和operator=
。副本的默认值肯定会做错事 - 它们只会复制指针值,而不会创建pimpl对象的新副本。由于这些函数周围的vector
个复制元素肯定会被调用。
答案 2 :(得分:0)
您只能通过指针或引用来执行多态操作。尝试使用vector<Shape*>
。
现在您正在使用指针,您必须为它们管理内存,但这是另一组问题。如果可以,尝试使用智能指针,如果不能,请小心使用。如果您使用的是C ++ 11,std::vector<std::unique_ptr<Shape>>
可能适合您。