2

The typical way of implementing IUnknown::QueryInterface() is the following: use a chain of if-else-if for each supported interface id and do the following:

if( iid == __uuidof( IInterfaceN ) ) {
   *ppv = static_cast<IInterfaceN>( this );
   //call Addref(), return S_OK
} 

Now static_cast is necessary here for proper pointer adjustment in multiple inheritance scenario.

Once in a while I see implementations that instead use dynamic_cast. IMO that's a waste of time - result will be the same, it'll just take longer and make the implementation overengineered.

Is there any case when using dynamic_cast is indeed necessary for casting this pointer before copying it into void** parameter of IUnknown::QueryInterface() implementation?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979

2 Answers2

1

It would be necessary in those implementations of QueryInterface where the "supported interface ids" aren't known. E.g. if you decide to implement QueryInterface in a base class, and not override it for every derived class.

A case where this would happen is the situation where you have a lot of similar types, where "similar" means "implementing many of the same interfaces". I.e. you have object types Derived1... DerivedN which all implement some subset of Interface1...InterfaceM.

This could be the case for a game engine where game entities all implement a subset of IMoveable, IScriptable, IFactory, IShoots, IPlayerControlled, IStealthy, ISensor, etcetera. Of course, by COM rules you must be able to call IFactory::QueryInterface and get an IMovable* if and only if the factory also implements IMovable.

How are you going to implement all those QueryInterface methods? It's easiest to insert an GameObject base class between IUnknown and IFactory, and implement GameObject::QueryInterface using dynamic_cast checks. In this way, you need only one implementation, instead of one per interface of a concrete type.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Emm... Could you please provide some simplest example of such hierarchy? – sharptooth Feb 03 '11 at 11:41
  • Assume a `Base` and a set of `Derived1`...`DerivedN` classes, where the `Derived` classes each implement a random subset of `Interface1`...`InterfaceM`. In `Base::QueryInterface`, you'd check if `this` can be `dynamic_cast` to the demanded interface. – MSalters Feb 04 '11 at 09:40
  • Okay, I see and it'a a valid example, although overengineered a bit. Could you please include it into the answer? – sharptooth Feb 04 '11 at 15:02
1

QueryInterface() is in fact an implementation of a "dynamic cast" operator. Basing the implementation on top of another implementation that requires another variant of the same metadata (inheritance tree) makes no real sense.

A good compiler should be able to remap this into a static_cast.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64