7


たとえば、2 つの「インターフェイス」とクラス タイプがあります。

class IPlugin
{
  public:
    virtual void Load(void) = 0;
    virtual void Free(void) = 0;
};

class IFoo
{
  public:
    virtual void Foo(void) = 0;
};


class Tester: public IPlugin, public IFoo
{
   public:
           Tester() {};
          ~Tester() {};

           virtual void Load()
           {
              // Some code here
           }

           virtual void Free()
           {
              // Some code here
           }

           virtual void Foo(void)
           {
              // Some code here
           }
 };

type のインスタンスに対して vtab が実際に持っている構造は何Testerですか? そして、 演算子はdynamic_castどのように動作しますか(dynamic_castつまり、演算子が有効な参照型変換のためにvtabをスキャンする方法を意味します)式:

Tester* t = new Tester();
IPlugin* plg = dynamic_cast<IPlugin*>(t);
IFoo* f = dynamic_cast<IFoo*>(plg);  

前もって感謝します!

4

4 に答える 4

18

C++ の仮想テーブルは実装の詳細です。考えられる実装の 1 つを下の図に示します。

仮想テーブルの図

クラスの 2 つのインスタンス (A と B) が存在します。各インスタンスには 2 つの vtbl ポインターがあり、vtbl には実際のコードへのポインターが含まれています。

あなたの例にはインスタンスデータはありませんが、説明のために、各クラスにインスタンスデータが含まれていると想定しています。

へのポインタがポインタへのポインタTesterにキャストされるとIFoo、ポインタは図に示すように調整されます。インスタンス データの先頭を指す代わりに、インスタンス データのIFoo一部を指します。

すばらしいことに、ポインターを使用する呼び出し元は、クラスIFooの一部を取り巻くデータについてまったく知識がありません。ポインターIFooを使用する呼び出し元についても同じことが言えます。IPluginこのポインターはたまたま、ポインターが指すインスタンス データの先頭を指していますが、ポインターTesterを使用する呼び出し元だけがTesterインスタンス データの全体のレイアウトを知っています。

使用dynamic_castには、図にない RTTI (Run-Time Type Information) が必要です。vtbl には追加の型情報が含まれてIFooおり、インスタンスへのポインターを指定するとTester、実行時にコードがポインターが指すオブジェクトの実際の型を検出し、それを使用してポインターをダウンキャストできます。

于 2011-05-03T12:16:56.593 に答える
6

vtab が Tester 型のインスタンスに対して実際に持っている構造は何ですか?

仮想ディスパッチのメカニズムは実装定義です。vtable と vptr は C++ 標準では要求されておらず、プログラマーが C++ でプログラミングするのにその知識は必要ありません。仮想テーブルにアクセスできないためです (コンパイラがこれを実装している場合でも)。コンパイラによって生成され、コードに追加されます。たとえば、コードを機械語に変換する前に、コードに対して多くのことを行います。


Tester* t = new Tester();
IPlugin* plg = dynamic_cast<IPlugin*>(t);
IFoo* f = dynamic_cast<IFoo*>(plg);  

ここdynamic_castは 2 行目では必要ありません。以下で十分です。

Tester* t = new Tester();
IPlugin* plg = t;                 //upcast          - dynamic_cast not needed
IFoo* f=dynamic_cast<IFoo*>(plg); //horizontal-cast - dynamic_cast needed

dynamic_castアップキャストでは必要ありません。ダウンキャストと水平キャストでのみ必要です。

Tester* tester1 = dynamic_cast<Tester*>(plg); //downcast - dynamic_cast needed
Tester* tester2 = dynamic_cast<Tester*>(f);   //downcast - dynamic_cast needed
于 2011-05-03T11:10:21.057 に答える
3

仮想メカニズム (仮想ポインターと仮想テーブル) は、C++ 標準では定義されていません。コンパイラが独自に選択した方法でメカニズムを実装することはできません。コンパイラの実装詳細です。そのため、コンパイラが仮想メカニズムを実装する方法の詳細は、ユーザーから抽象化されます。重要なのは、仮想メカニズムから予想される動作のみです。

あなたの場合:

Tester* t = new Tester(); 
IPlugin* plg = dynamic_cast<IPlugin*>(t); 
IFoo* f = dynamic_cast<IFoo*>(plg);   

plg& both は両方から派生してfいるため、それぞれの型の有効なオブジェクトを指します。t

もちろん、これはあなたが尋ねた特定の質問には答えませんが、コンパイラの実装の詳細である仮想メカニズムの詳細を明確にしたかっただけです。

于 2011-05-03T11:12:29.507 に答える