如何在运行时决定在C ++中使用哪个派生类作为私有类成员?

时间:2013-02-23 22:42:29

标签: c++ class inheritance virtual

以下问题对我来说有点难以制定,但请耐心等待,如果我能帮忙清除任何问题,请告诉我。

我正在为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>

以某种方式可以做到这一点吗?感谢

3 个答案:

答案 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>>可能适合您。