0

これがどこかに文書化されているかどうかはわかりません。仮想関数の場合、各クラスは、仮想テーブルと呼ばれる関数ポインターの配列を指す vptr を保持します。vptr のプロトタイプを知りたいです。たとえば、クラスが次のように宣言されている場合、

class A
{
   int a;
   public: A(){}
   virtual void display();
   virtual void setValue(int x);
};

現在、クラス A の vtable に 2 つの関数ポインタがあります。1 つの vptr で異なるプロトタイプの 2 つの定義を実行するにはどうすればよいでしょうか?

私の理解が間違っている場合はお知らせください。

どうも!ラフル。

4

3 に答える 3

3

vptr は実装の詳細であるため、プロトタイプはありません。

于 2012-06-03T17:40:55.917 に答える
1

仮想テーブル (そのようなものを使用する実装) は、「コンパイラの魔法」の産物です。C++ コードで直接使用されることはないため、特定のプロトタイプを持つ必要はありません。代わりに、コンパイラは、1 つを必要とする各クラスに適合するように 1 つをカスタム生成します。コンパイラは、各要素にアクセスするためのコードも生成するため、各要素がタイプ セーフな方法でアクセスされることを保証できます。

たとえば、コンパイラは、メソッドのスロットが署名A::setValueに一致する関数へのポインターを保持していることを認識しています。これは、最初にそれを配置したのがコンパイラであるためです。setValueさらに、そのスロットに直接アクセスする唯一のコードは、コンパイラが生成したマシン コードであり、そのようなコードを生成する前に、コンパイラは元の C++ コードがsetValue関数を呼び出していることを既に確認していました。したがって、スロットが-conformant 関数ポインターsetValue以外のものを保持できるという心配はありません。setValueまた、代わりに他のスロットがアクセスされる可能性があるという懸念もありません。それが起こった場合、それはコンパイラのバグであり、通常のユーザー コードの結果として発生するものではありません。

テーブルの要素がグループとして扱われることはないため、すべてが同じ型である必要はありません。せいぜい、それらはすべて「CPUがジャンプするのに適した一般的なポインターまたはオフセット」のタイプを持っています。その時点では実際には C++ ではないため、「型」は特定の C++ 型に適合する必要はありません。

于 2012-06-03T18:16:29.243 に答える
1

Oli Charlesworth が指摘したように、仮想ポインタは実装の詳細であるため、この質問は C++ に関してはあまり意味がありません。そうは言っても、次の仮想関数 (機能の一部) の手動実装は、理解に役立つ場合があります。

struct vtable {
    void (*display)(void*);
    void (*setValue)(void*, int);
};

void A_display(void *this_) { /*Cast this_ to A* and do A stuff*/ }
void A_setValue(void *this_, int x) { /*Cast this_ to A* and do A stuff*/ }

vtable A_vtable = {A_display, A_setValue};

struct A {
    vtable *vptr = &A_vtable;
    int a;
    public: A(){}
};

void B_display(void *this_) { /*Cast this_ to B* and do B stuff*/ }
void B_setValue(void *this_, int x) { /*Cast this_ to B* and do B stuff*/ }

vtable B_vtable = {B_display, B_setValue};

struct B {
    vtable *vptr = &B_vtable;
    int a;
    public: B(){}
};

void display(void *obj) {
    ((*static_cast<vtable**>(obj))->display)(obj);
}
void setValue(void *obj, int) {
    ((*static_cast<vtable**>(obj))->setValue)(obj, int);
}

もちろん、これは仮想関数の機能のごく一部しか示していませんがvptrs、固定型の関数へのポインターのコレクションを指していることを理解するのはかなり簡単です。

于 2012-06-03T18:13:31.353 に答える