1

仮想関数を持つ空のクラスがあるとしましょう:

class Base
{
public:
    virtual void Foo(){std::cout << "this is the base class";}
}

次に、継承しBaseてオーバーライドするクラスがありますFoo()

class Derived : public Base
{
public:
    void Foo(){std::cout << "this is the derived class";}
}

次に、次のリストを含む他のクラスがありますBase

class OtherClass
{
public:
    std::vector<Base> listOfBases; //note it's not std::list<Derived>
}

クラスではなく、クラスを循環してlistOfBases呼び出すFoo()にはどうすればよいですか? 今私が言うなら、これは基本クラスが印刷されますが、クラスからオーバーライドされたものを印刷したいと思います。DerivedBaselistOfBases[i].Foo();Derived

Derivedの代わりにのリストにするだけでBase修正できますが、これらの継承されたクラスをあらゆる種類のものと呼ぶので、 のリストが必要ですBase

では、基本クラスのリストからオーバーライドされた関数を呼び出すにはどうすればよいでしょうか?

4

2 に答える 2

3

Base*のリスト(つまり、Base へのポインター)、またはできれば、std::unique_ptr<Base>またはを使用する必要がありますstd::shared_ptr<Base>

この理由は、C++ オブジェクト モデルとコピーのためです。派生クラスは、少なくとも基本クラスと同じ大きさである必要があります (派生クラスが空であるかどうかに応じて、同じサイズにすることができます)。C++ はアイテムを a に追加するときにコピー (または C++11 では移動) を利用するvectorため、n 個Baseのオブジェクトに十分なスペースを割り当てる必要があります。avectorはほとんどの場合単純な のラッパーであるため、(サイズが異なる可能性がある)オブジェクトをofオブジェクトarrayに追加しようとすると、未定義の動作になります。DerivedarrayBase

于 2012-12-17T00:47:14.547 に答える
0

各基本クラスへのポインターを取得し、それを派生クラスにダウンキャストします。UML ダイアグラムでは、基本クラスを派生クラスの上に描画するのが慣例であるため、ダウンキャストと呼ばれます。

for ( auto q = listOfBases.begin(); q != listOfBases.end(); ++q )
{
    Base* pBase = &(*q); // Get pointer to Base class. Can't downcast on object.
    Derived* pDerived = dynamic_cast<Derived*>(pBase); // Downcast
    pDerived->Foo();   // Call Foo() of Derived
} 
于 2012-12-17T00:53:27.107 に答える