Compartir a través de


Preguntar a un objeto para una interfaz

Hemos visto anteriormente que un objeto puede implementar más de una interfaz. El objeto Common Item Dialog es un ejemplo real de esto. Para admitir los usos más típicos, el objeto implementa la interfaz IFileOpenDialog . Esta interfaz define métodos básicos para mostrar el cuadro de diálogo y obtener información sobre el archivo seleccionado. Sin embargo, para un uso más avanzado, el objeto también implementa una interfaz denominada IFileDialogCustomize. Un programa puede usar esta interfaz para personalizar la apariencia y el comportamiento del cuadro de diálogo agregando nuevos controles de interfaz de usuario.

Recuerde que todas las interfaces COM deben heredar, directa o indirectamente, de la interfaz IUnknown . En el diagrama siguiente se muestra la herencia del objeto Dialog de elemento común.

diagrama que muestra las interfaces expuestas por el objeto de diálogo de elemento común

Como puede ver en el diagrama, el antecesor directo de IFileOpenDialog es la interfaz IFileDialog , que a su vez hereda IModalWindow. A medida que sube la cadena de herencia de IFileOpenDialog a IModalWindow, las interfaces definen una funcionalidad de ventana cada vez más generalizada. Por último, la interfaz IModalWindow hereda IUnknown. El objeto Common Item Dialog también implementa IFileDialogCustomize, que existe en una cadena de herencia independiente.

Ahora supongamos que tiene un puntero a la interfaz IFileOpenDialog . ¿Cómo se obtiene un puntero a la interfaz IFileDialogCustomize ?

diagrama que muestra dos punteros de interfaz a interfaces en el mismo objeto

Simplemente convertir el puntero IFileOpenDialog a un puntero IFileDialogCustomize no funcionará. No hay ninguna manera confiable de "conversión cruzada" en una jerarquía de herencia, sin alguna forma de información de tipo en tiempo de ejecución (RTTI), que es una característica altamente dependiente del lenguaje.

El enfoque COM consiste en pedir al objeto que le proporcione un puntero IFileDialogCustomize , utilizando la primera interfaz como un conducto en el objeto. Esto se hace llamando al método IUnknown::QueryInterface desde el primer puntero de interfaz. Puede considerar QueryInterface como una versión independiente del lenguaje de la palabra clave dynamic_cast en C++.

El método QueryInterface tiene la siguiente firma:

HRESULT QueryInterface(REFIID riid, void **ppvObject);

En función de lo que ya sabe sobre CoCreateInstance, es posible que pueda adivinar cómo funciona QueryInterface .

  • El parámetro riid es el GUID que identifica la interfaz que solicita. El tipo de datos REFIID es una definición de tipo para const GUID&. Observe que el identificador de clase (CLSID) no es necesario, porque el objeto ya se ha creado. Solo es necesario el identificador de interfaz.
  • El parámetro ppvObject recibe un puntero a la interfaz. El tipo de datos de este parámetro es void**, por la misma razón por la que CoCreateInstance usa este tipo de datos: QueryInterface se puede usar para consultar cualquier interfaz COM, por lo que el parámetro no se puede escribir fuertemente.

Aquí se muestra cómo llamaría a QueryInterface para obtener un puntero IFileDialogCustomize :

hr = pFileOpen->QueryInterface(IID_IFileDialogCustomize, 
    reinterpret_cast<void**>(&pCustom));
if (SUCCEEDED(hr))
{
    // Use the interface. (Not shown.)
    // ...

    pCustom->Release();
}
else
{
    // Handle the error.
}

Como siempre, compruebe el valor devuelto HRESULT , en caso de que se produzca un error en el método. Si el método se realiza correctamente, debe llamar a Release cuando haya terminado de usar el puntero, como se describe en Administración de la duración de un objeto.

Siguientes

Asignación de memoria en COM