2

下面这个问题对我来说有点难以表述,但请耐心等待,如果我能帮助解决任何问题,请告诉我。

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

我当然理解错误消息和我的错误,但我仍然不明白如何解决它。

我希望能够做的是将向量的类型保留为未定义,然后当我知道用户选择了哪种模拟类型时,只需在运行时使用正确的派生类通过构造函数创建它。

有没有可能做到这一点?谢谢

4

3 回答 3

2

使用(智能)指针

您不能实例化抽象类,即使可以,也可能不是您想要的,因为您无法创建这些形状的别名

您应该将您的SimulationControl类的定义更改为与此更相似的定义(假设您的形状在这里共享所有权 - 如果SimulationControl是您的形状的唯一所有者,而不是使用unique_ptr而不是shared_ptr):

#include <memory>

class SimulationControl {
    public:
        void runsimulation();
    private:

        std::vector<std::shared_ptr<Shape>> all_shapes;
    ...
};

然后,您可以创建形状的实例并将它们添加到all_shapes集合中,如下所示(假设MyShape是一个具体的、默认可构造的类派生自Shape):

std::shared_ptr<MyShape> pShape = std::make_shared<MyShape>();

pShape->set_vertices(...); // I guess the class will have a member function
                           // that allows setting the shape's vertices...

all_shapes.push_back(pShape);
于 2013-02-23T22:51:17.150 回答
2

我不会跟风并建议在你的容器中使用指针,无论是聪明的还是愚蠢的。这是使用PIMPL 成语的绝佳机会。

这个想法是,该类只是实际实现的包装器,并在对其进行调用时调用指向另一个对象的指针。包装器中包含的指针可以是多态的,因此它可以实现它认为合适的功能。

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该类包含一个指针,所以您需要实现三规则并创建析构函数、复制构造函数和operator=. 副本的默认值肯定会做错事——它们只会复制指针值,而不会创建 pimpl 对象的新副本来与它们一起使用。由于 avector复制这些函数周围的元素肯定会被调用。

于 2013-02-23T23:00:06.423 回答
0

您只能通过指针或引用进行多态性。尝试使用vector<Shape*>.

现在您正在使用指针,您必须为它们管理内存,但这是另一组问题。如果可以,请尝试使用智能指针,如果不能,请非常小心。如果您使用的是 C++11,std::vector<std::unique_ptr<Shape>>可能适合您。

于 2013-02-23T22:51:06.337 回答