1

解決済みを編集してサンプルプログラムとして再投稿

シナリオは次のとおりでした。

クラス階層:

class Base
{
public:
   virtual void output() = 0;
private:
   int a;
};

class Derived_1 : public Base
{
public:
   virtual void output()
   {
      cout << "Derived_1" << endl;
   }
};

class Derived_2 : public Derived_1
{
public:
   virtual void output()
   {
      cout << "Derived_2" << endl;
   }
};

実装:

Derived_2* obj = reinterpret_cast<Derived_2*>(new Derived_1());
obj->output();

これにより、「Derived_2」ではなく「Derived_1」が出力されます。これはほとんどの人にとって目新しいことではないと思いますが、アプリケーションでいくつかのファクトリ関数を作成するときに考えたこともありませんでした。

4

3 に答える 3

3

Value_object_dataではなく、オブジェクトを割り当てていますValue_object_uint32。としてキャストしているという事実は、Value_object_uint32何も変わりません。実際のオブジェクトの仮想テーブルには の知識がありませんValue_object_uint32。err... 構築時に構築される仮想関数テーブルで、 をformat指しValue_object_dataますformat。実際のオブジェクトを指すポインターのタイプを強力に武装しても、状況は修正されません。

特定の階層内のすべての基本クラスおよび継承クラスのコンストラクターは、最も派生したクラスからルートに向かって、クラスごとに 1 回だけ呼び出されます。つまり、基本クラスのコンストラクターを明示的に呼び出す必要はありません。自動的に呼び出されます。いくつかの基底クラス コンストラクターのどれを使用するかを指定する必要がある場合は、それも行うことができます。

class Base
{
public:
    Base() {} // default constructor
    Base(int a) {}
};

class Derived
{
public:
    Derived() : Base()
    {
    }

    Derived(int a)
      : Base(a) // Select the Base ctor that takes an int, instead of the default
    {
    }
};

int main()
{
    Derived d1;    // Calls Derived() and Base() ctors in this order
    Derived d2(5); // Calls Derived(5) and Base(5) in this order
}

もちろん、Derived(int a)コンストラクターはコンストラクターを呼び出す必要はありませんBase(int)。この場合、Base()コンストラクターは自動的に呼び出されます。

于 2012-05-10T21:23:16.317 に答える
3

編集この回答は、投稿された元のコードに基づいています。OP は、切り捨てられた例が期待どおりに機能することを確認した後、コード サンプルを更新しました。


あなたのコードは正確ではありませんが、このようなことが起こる最も一般的な理由は、オーバーライドしようとしたときに署名が正確に取得されず、代わりにオーバーロードを作成したことです。基本クラスを介して呼び出すと、正しく定義されたクラスが呼び出されます。

署名のすべてが重要です。よくある間違いは、メソッドの constness が署名の一部であるということです。

于 2012-05-10T19:37:51.723 に答える
0

少なくとも、new_VO_data()メソッドは壊れています。可変の仮想テーブルサイズと可変のパディングが原因で機能する場合と機能しない場合があります。これらは標準では任意であり、コンパイラオプションによって異なります。簡単に言えば、動作は未定義です。

于 2012-05-10T21:22:05.273 に答える