2010-06-13 29 views
5

Estoy tratando de comprender this example code con respecto a los objetos del navegador.¿Cómo funciona la implementación de múltiples interfaces COM en C++?

En el interior, el autor implementa una única clase que expone múltiples interfaces (IObjectWithSite, IDispatch).

Su función QueryInterface realiza lo siguiente:

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

He aprendido que desde una perspectiva de C, punteros de interfaz son sólo punteros a vtables. Así que lo interpreto como que C++ es capaz de devolver la VTable de cualquier interfaz implementada usando static_cast.

¿Esto significa que una clase construida de esta manera tiene un montón de VTables en memoria (IObjectWithSite, IDispatch, etc.)? ¿Qué hace C++ con las colisiones de nombres en las diferentes interfaces (cada una tiene una función QueryInterface, AddRef y Release)? ¿Puedo implementar diferentes métodos para cada una de ellas?

Respuesta

6

Sí, hay varias tablas v, una para cada interfaz heredada. El static_cast <> lo devuelve. El compilador se asegura de que se compartan los métodos comunes en las interfaces heredadas, rellena cada ranura de la tabla v con un puntero a la misma función. Por lo tanto, solo necesita una implementación de AddRef, Release, QueryInterface. Justo lo que quieres Nada de esto es un accidente.

Esto es siempre un problema cuando un coclass implementa múltiples interfaces con el mismo método que usted no desea quiere dar la misma implementación. El método IConnectionPoint :: Advise() es un ejemplo notorio. ¿O era DAdvise()? Desafortunadamente, no recuerdo con qué chocó y cómo se resolvió, fue cubierto por ATL Internals. Muy buen libro por cierto.

+1

Gracias! He hecho algunas lecturas propias y descubrí que no solo crea diferentes VTables, sino que también crea funciones "thunk" para reparar el puntero antes de redirigir a la función común. – Martin

3

En la herencia múltiple, múltiples vtables están dispuestos en secuencia como formato siguiente si se les da this puntero (que seleccione primero byte, 01)

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

En C++, se generará solamente 1 aplicación por prototipo de función en el escenario de múltiples interfaces. Sin embargo, para el escenario de herencia normal, la superclase podría tener una implementación predefinida y los hijos que sobrescriban la función tendrán sus tablas virtuales apuntando a un contenido diferente al principal.

Cuestiones relacionadas