30

vtableはメモリのどこに保存されますか?

4

6 に答える 6

50

コンパイラによって異なります。

VC ++では、vtableポインターは、オブジェクト割り当ての先頭で、メンバーデータの前に格納されます。(クラスに少なくとも1つの仮想メンバー関数がある場合。)

クラスがvtablesを持つ他のクラスから複数継承する場合は、複数のvtableポインタが存在する可能性もあります。

vtable自体は、アドレス空間のどこかに静的に割り当てられます。

次に、オブジェクトのレイアウトは次のようになります(Cのインスタンスの場合)。

A's VTable ptr
A's member variables.
B's Vtable ptr
B's member variables.
C's member variables.

階層のために

class A {
  virtual Ax() {}
  int a, b;
};
class B {
  virtual Bx() {}
  int c, d;
};
class C : public A, public B {
  int foo, bar;
};
于 2009-12-15T04:55:48.830 に答える
17

Vtable?どのvtable?C ++標準では、vtableについては言及されていません。各コンパイラは、仮想関数を好きなように実装できます。これには、vtableを好きな場所に配置することも含まれます。

于 2009-12-15T12:50:53.597 に答える
3

VC++の場合

于 2009-12-15T04:59:13.843 に答える
2

通常、オブジェクトの先頭にあるvptr(Imperfect C ++Backyard Hotrodding C ++)ですが、標準では保証されていません。vptrsとvtablesの使用は、標準では保証されていません。

それがどこにあるかを本当に知る必要がある場合は、基本的にvptrのようなものが配置されている場所を設定し、それらの使用方法を設定することによって実装されるCOM、XPCOM、UNOなどのようなものを使用するのが一般的です。

于 2009-12-15T08:04:28.640 に答える
-1

仮想関数を含むすべてのインスタンスには、仮想関数テーブル(vbtl)を指す仮想関数ポインターがあります。インスタンスからvtblを見つけることしかできませんでした。または、objdumpを使用してELFファイルのシンボルを読み取ることができます。おそらく、答えを見つけることができます。次の例があなたを助けてくれることを願っています。

#include <iostream>
#include <stdio.h>
typedef void (*fun_pointer)(void);

using namespace std;
class Test
{
 public:
   Test()
    {
     cout<<"Test()."<<endl;
    }
   virtual void print()
    {
     cout<<"Test::Virtual void print()."<<endl;
    }
   virtual void print2()
    {
     cout<<"Test::virtual void print2()."<<endl;
    }
};

class TestDrived:public Test
{
 public:
  TestDrived()
    {
    cout<<"TestDrived()."<<endl;
    }
  virtual void print()
    {
    cout<<"TestDrived::virtual void print()."<<endl;
    }
  virtual void print2()
    {
    cout<<"TestDrived::virtual void print2()."<<endl;
    }
  void GetVtblAddress()
    {
        cout<<"vtbl address:"<<(int*)this<<endl;
    }
  void GetFirstVtblFunctionAddress()
    {
    cout<<"First vbtl function address:"<<(int*)*(int*)this+0 << endl;
    }
  void GetSecondVtblFunctionAddress()
    {
    cout<<"Second vbtl function address:"<<(int*)*(int*)this+1 << endl;
    }
  void CallFirstVtblFunction()
    {
    fun = (fun_pointer)* ( (int*) *(int*)this+0 );
    cout<<"CallFirstVbtlFunction:"<<endl;
    fun();
    }
  void CallSecondVtblFunction()
    {
    fun = (fun_pointer)* ( (int*) *(int*)this+1 );
    cout<<"CallSecondVbtlFunction:"<<endl;
    fun();
    }
private:
    fun_pointer fun;
};



int main()
{
 cout<<"sizeof(int):"<<sizeof(int)<<"sizeof(int*)"<<sizeof(int*)<<endl;
 fun_pointer fun = NULL;
 TestDrived a;
 a.GetVtblAddress();
 a.GetFirstVtblFunctionAddress();
 a.GetSecondVtblFunctionAddress();
 a.CallFirstVtblFunction();
 a.CallSecondVtblFunction();
 return 0;
}
于 2013-06-21T16:58:21.843 に答える
-2

VptrとVtableはデータセグメントに保存されます。

Vtableは、関数ポインタの配列のようなものです。

VtableとVptrはコンパイル時に作成され、実行時にメモリを取得します。vtableエントリは仮想関数アドレスです。

仮想関数を含むクラスのすべてのオブジェクトには、仮想テーブルを指す追加のポインターがあります。これは仮想ポインターと呼ばれます。

オブジェクトを使用して仮想関数を呼び出すときは常に、最初に対応するVptrが実行時にVtableから関数を読み取り、最後に関数が呼び出されます。

于 2016-04-20T05:26:14.827 に答える