5

ブラウザヘルパーオブジェクトに関するこのサンプルコードを理解しようとしています。

内部では、作成者は複数のインターフェイス(IObjectWithSite、IDispatch)を公開する単一のクラスを実装します。

彼のQueryInterface関数は次のことを実行します。

if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this);
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this);
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this);

Cの観点からは、インターフェイスポインターはVTableへの単なるポインターであることを学びました。つまり、C++はstatic_castを使用して実装されたインターフェイスのVTableを返すことができるということです。

これは、この方法で構築されたクラスがメモリ内に多数のVTable(IObjectWithSite、IDispatchなど)を持っていることを意味しますか?C ++は、さまざまなインターフェイス(それぞれにQueryInterface、AddRef、およびRelease関数があります)での名前の衝突をどのように処理しますか?これらのそれぞれに異なるメソッドを実装できますか?

4

2 に答える 2

7

はい、継承されたインターフェイスごとに 1 つずつ、複数の v テーブルがあります。static_cast<> はそれを返します。コンパイラは、継承されたインターフェイスの共通メソッドが共有されていることを確認し、各 v-table スロットを同じ関数へのポインターで埋めます。したがって、AddRef、Release、QueryInterface の 1 つの実装のみが必要です。欲しいものだけ。これはどれも事故ではありません。

これは、コクラスが同じメソッドを使用して複数のインターフェイスを実装し、同じ実装を提供したくない場合にのみ問題になります。IConnectionPoint::Advise() メソッドは悪名高い例です。それとも DAdvise() でしたか?残念ながら、それが何と衝突し、どのように解決されたかは覚えていません。ATL Internals でカバーされていました。ところで非常に良い本。

于 2010-06-14T00:32:53.613 に答える
3

this多重継承では、複数の VTable は、ポインタ (最初のバイト 01 を指す) を指定すると、次の形式のように順番に配置されます。

[01][02][03][04] [05][06][07][08] [09][10][11][12]
[VTableAのPtr][VTableBのPtr][VTableCのPtr] ]

C++ では、複数インターフェイスのシナリオでは、関数プロトタイプごとに 1 つの実装のみが生成されます。ただし、通常の継承シナリオの場合、スーパークラスには事前定義された実装があり、関数をオーバーライドする子は、親とは異なるコンテンツを指す VTable を持ちます。

于 2010-06-14T01:25:39.903 に答える