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

私は時流に乗って、賢いか愚かかにかかわらず、コンテナー内でポインターを使用することを提案するつもりはありません。これは、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クラスにはポインターが含まれているため、3 つのルールを実装して、デストラクタ、コピー コンストラクタ、およびoperator=. コピーのデフォルトは確かに間違ったことをします - それらはポインタ値をコピーするだけで、それらに合わせて pimpl オブジェクトの新しいコピーを作成しません。vectorこれらの関数の周りの要素をコピーするため、確実に呼び出されます。

于 2013-02-23T23:00:06.423 に答える
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と仮定します)。MyShapeShape

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 に答える
0

ポインターまたは参照によるポリモーフィズムのみを行うことができます。を使ってみてくださいvector<Shape*>

ポインタを使用するようになったので、ポインタのメモリを管理する必要がありますが、それは別の問題です。可能であればスマート ポインターを使用するようにしてください。不可能な場合は十分に注意してください。C++11 を使用している場合は、std::vector<std::unique_ptr<Shape>>あなたにぴったりかもしれません。

于 2013-02-23T22:51:06.337 に答える