2

巨大なコード ベースのバグを修正しているときに、参照の動的な型が元のDerived型からBase型に変わる奇妙な状況を観察しています。問題を説明するための最小限のコードを提供しています。

struct Base {
  // some 'virtual' function
  protected: // copy constructor
  private:  // assignment operator
};

struct Derived : Base {
  ... // There are few more classes between `Base` and `Derived`
  ... // but for simplicity, I have put direct relation
};

void foo (Base &ref)
{
  SomeClass obj;
  obj.pVoid = &ref;  // pVoid is of void*

  // ----> typeid(ref) = Derived
  (*funcptr)(obj);
  // ----> typeid(ref) = Base !!!

  Derived *p = dynamic_cast<Derived*>(&ref);  // this fails ... i.e. "p = 0"
}

funcptrは関数ポインタ ( void (*)(SomeClass&)) です。 funcptr非常に多くの関数を指すことができ、独自の呼び出しフローがあるため、デバッグが困難になります。

関数ポインターを呼び出した後、 の派生型が からにref変わるのは非常に奇妙です。作業を楽にするために、 からへのオブジェクト スライスを疑ったので、ソース コード全体をピュアとして作成し、再コンパイルしました。しかし、コンパイラエラーはありませんでした。つまり、宣言されるオブジェクトはありません。DerivedBaseDerivedBase~Base()virtualBase

の動的タイプref Derivedが に変更されBasedynamic_cast後で失敗する潜在的な理由は何ですか?

4

3 に答える 3

0

dynamic_cast<>私の特定のケースで失敗した理由はdelete、時期尚早に参照を行ったためです!

+ポインタまたは参照がdelete破棄されると、それを元の型にダウンキャストしようとすると、「未定義の動作」領域に入る結果になります。私の場合、dynamic_cast<>失敗しています。

void foo (Base &ref)
{
  SomeClass obj;
  obj.pVoid = &ref;

  (*funcptr)(obj);  // ----> delete (Base*)(obj.pVoid); in one of the callbacks

  Derived *p = dynamic_cast<Derived*>(&ref);  // fails => "p = 0"
}
于 2012-02-13T14:29:45.880 に答える