views:

66

answers:

2

I am trying to understand this example code regarding Browser Helper Objects.

Inside, the author implements a single class which exposes multiple interfaces (IObjectWithSite, IDispatch).

His QueryInterface function performs the following:

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);

I have learned that from a C perspective, interface pointers are just pointers to VTables. So I take it to mean that C++ is capable of returning the VTable of any implemented interface using static_cast.

Does this mean that a class constructed in this way has a bunch of VTables in memory (IObjectWithSite, IDispatch, etc)? What does C++ do with the name collisions on the different interfaces (they each have a QueryInterface, AddRef and Release function), can I implement different methods for each of these?

+3  A: 

Yes, there are multiple v-tables, one for each inherited interface. The static_cast returns it. The compiler makes sure that common methods in the inherited interfaces are shared, it fill each v-table slot with the a pointer to the same function. So you only need one implementation of AddRef, Release, QueryInterface. Just what you want. None of this is an accident.

This is only ever a problem when a coclass implements multiple interfaces with the same method that you don't want to give the same implementation. The IConnectionPoint::Advise() method is a notorious example. Or was it DAdvise()? Unfortunately, I don't remember what it clashed with and how it was solved, it was covered by ATL Internals. Very good book btw.

Hans Passant
Thanks! I have done some reading of my own and I discovered that it not only creates different VTables, but also creates "thunk" functions to fixup the pointer before redirecting back to the common function.
Martin
+1  A: 

In multiple inheritance, multiple VTables are arranged in sequence like following format if given this pointer (which point to first byte, 01)

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

In C++, only 1 implementation will be generated per function prototype in multiple interface scenario. However for normal inheritance scenario, superclass might have pre-defined implementation and children who overrides the function will have their VTables pointing to different content than the parent.

YeenFei