クラス内のvtableメンバーの順序は明確に定義されていません。確かに、vtableポインタ間でデータメンバーを見つけることができます(そしてそうなります)。あなたはCOMを書いている場合は、あなたが前にあなたが結果を入れているポインタに書き込むには、あなたのQueryInterface
に戻るには、好きなインターフェイスにキャストする必要があることは、のようなものです:。
HRESULT QueryInterface(REFIID riid, LPVOID *ppvObject) {
if (*riid == IID_MY_INTERFACE) {
*ppvObject = static_cast<IMyInterface *>(this);
return S_OK;
} else if (*riid == IID_SOMETHING_ELSE) {
*ppvObject = static_cast<ISomethingElse *>(this);
return S_OK;
} else /* ... */
}
コンパイラあなたのためのインターフェイスのための右のオフセットを見つけるの世話をするでしょう。
それが実際にどのように動作するかについては、これが意味するものについて考える - の各インターフェイスは、オブジェクト内のオフセットのいくつかのサブレンジのオブジェクトとして存在している必要があります..あなたはこのようになりますクラスの階層構造があるだろう:
を
class IA { virtual void foo() = 0; int x;};
class IB { virtual void bar() = 0; int y; };
class C : public IA, public IB { int bar; };
あなたのメモリ内のレイアウトは、次のようになります。ここでは
00000000 vtable ptr for C
00000004 vtable ptr for Ia
00000008 int x
0000000b vtable ptr for Ib
00000010 int y
00000014 int bar
あなたは0x0000000b
でクラスへのオフセット0x00000004
を取得、またはIbによりIaのへのポインタを取得することができます。
ことが可能によるいくつかのケースではこれをさらに最適化することがあります。
00000000 vtable ptr for C and Ia
00000004 int x
00000008 vtable ptr for Ib
0000000b int y
00000010 int bar
Iは、Win32のC++ ABIは実際にこれを行うかはわかりません。これを行うと、C vtableはIa vtableと同じメンバーで始まり、最後に余分なものが追加されます。
VC++の実装についての古い記事がありますが(http://www.openrce.org/articles/files/jangrayhood.pdf)、基本原則は変更されていないと思います実装は異なります)。 –
なぜそれは重要ですか? vtablesは実装の詳細です。 C++標準にはvtableの概念はありません。 – fredoverflow
@FredOverflow悲しいことに、COMオブジェクトインターフェイスはvtable実装にマップされます。それはおそらくCOMの質問として興味深いだけです。 –