7

私は最近、C/C++ が主要な言語であるポジションの面接を受けました。ある質問の中で、vtable を使用して、階層内のどのクラスのベース ポインターが実際に格納されているかを判断できると言われました。

たとえば、あなたが持っている場合

    class A  
    {  
    public:  
    A() {}  
    virtual ~A() {}  
    virtual void method1() {}  
    };

    class B : public A  
    {  
    public:  
    B() {}  
    virtual ~B() {}  
    virtual void method1() {}  
    };

インスタンス化A * pFoo = new B()すると、vtable を使用して pFoo に A または B のインスタンスへのポインタが含まれているかどうかを判断することは本当に可能ですか?

4

4 に答える 4

12

これは明らかに実装に依存しますが、ほとんどの実装では、クラスのオブジェクトのメモリ内表現、AまたはBvtableへのポインタで始まります。このvtableポインターを見て、クラスAまたはBであることがわかっているオブジェクトのvtableポインターと比較し、その方法でオブジェクトのクラスを判別できます。

説明するために(もちろんこれは良いスタイルではありません):

A *pFoo=new B(); // pointer to object of unknown class (either A or B)
A a;  // Object known to be of class A
B b;  // Object known to be of class B
void *vptrA=*((void **)&a);  // Pointer to vtable of class A
void *vptrB=*((void **)&b);  // Pointer to vtable of class B
void *vptrFoo=*((void **)pFoo);  // Pointer to vtable of unknown object
if(vptrFoo==vptrA)
    printf("Class A\n");
else
    printf("Class B\n");

重要:これは、ほとんどの実装がどのように機能するかを示したものにすぎません。この手法は、実装に依存するだけでなく、多重継承が存在する場合に機能しなくなります。本番コードでは、このようなことは絶対にしないでください。代わりにRTTIを使用してください。

于 2010-06-09T14:33:03.193 に答える
4

はい、それはかなり可能です-dynamic_castを使用してください。これはかなりくだらない質問です-少し良い質問は「dynamic_castはどのように実装されていますか?」かもしれません。しかし、実際にインタビューでどちらかを尋ねられた場合、私はインタビュアーのヌースについて疑問に思う必要があります。優れた、あるいは優れたC ++プログラマーであるためには、このような実装の詳細を知る必要はありませんが、もちろん、これらは2番目の評価者が尋ねるのは簡単な質問です。

于 2010-06-09T15:29:02.683 に答える
2

typeid() 関数を確認してください。

于 2010-06-09T15:43:36.420 に答える
1

vpointer にアクセスでき、vpointer を介してクラス内の任意の仮想メソッドを呼び出すこともできます。しかし、これは悪であることを忘れないでください。

例 :

class A
{
public:
    void f1()
    {
        cout<<"bbb"<<endl;;
    }
    virtual void f2()
    {
        cout<<"ccc"<<endl;;
    }
    virtual void f3()
    {
        cout<<"ddd"<<endl;;
    }
};

メインで呼び出す

A a;

typedef void (__thiscall* foo)();
(*(foo)((void**)(((void**)(&a))[0]))[1])();

vpointer にアクセスし、次にインデックスで移動し、vTable の 2 番目のメソッドである f3() を実行します。

すでに提案されているように、RTTI を使用することにも注意してください。

于 2010-06-09T14:44:19.360 に答える