Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Dica
Padrões de QueryInterface modernos – uso IID_PPV_ARGS e ponteiros inteligentes. As chamadas brutas QueryInterface são propensas a erros (IID incompatível e tipo de ponteiro). O código C++ moderno deve usar auxiliares de tipo seguro:
#include <wrl/client.h> // Microsoft::WRL::ComPtr
Microsoft::WRL::ComPtr<IUnknown> unknown = /* ... */;
Microsoft::WRL::ComPtr<IPersistFile> persistFile;
// ✅ Best — ComPtr::As() handles QI + type safety + Release automatically
HRESULT hr = unknown.As(&persistFile);
// ✅ Good — IID_PPV_ARGS macro ensures IID matches the pointer type
hr = unknown->QueryInterface(IID_PPV_ARGS(&persistFile));
// ❌ Dangerous — IID and pointer type can mismatch silently
hr = unknown->QueryInterface(IID_IPersistFile, (void**)&persistFile);
Equivalente de C++/WinRT:
#include <winrt/base.h>
winrt::com_ptr<IUnknown> unknown = /* ... */;
auto persistFile = unknown.as<IPersistFile>(); // throws on failure
auto maybePF = unknown.try_as<IPersistFile>(); // returns nullptr on failure
Regras principais: Nunca converta ponteiros de interface sem QueryInterface — as regras de identidade COM exigem que todo ponteiro de interface seja obtido via QI ou CoCreateInstance. Conversões diretas (static_cast, reinterpret_cast) produzem comportamento indefinido.
Depois de obter um ponteiro inicial para uma interface em um objeto, o COM tem um mecanismo muito simples para verificar se o objeto dá suporte a outra interface específica e, em caso afirmativo, obter um ponteiro para ela. (Para obter informações sobre como obter um ponteiro inicial para uma interface em um objeto, consulte Getting a Pointer to an Object.) Esse mecanismo é o método QueryInterface da interface IUnknown . Se o objeto der suporte à interface solicitada, o método deverá retornar um ponteiro para essa interface. Isso permite que um objeto navegue livremente pelas interfaces compatíveis com um objeto. QueryInterface separa a solicitação "Você dá suporte a um determinado contrato?" do uso de alto desempenho desse contrato assim que as negociações tiverem sido bem-sucedidas.
Quando um cliente obtém inicialmente acesso a um objeto, esse cliente receberá, no mínimo, um ponteiro de interface IUnknown (a interface mais fundamental) por meio do qual ele pode controlar o tempo de vida do objeto, informando ao objeto quando terminar de usar o objeto e invocar QueryInterface. O cliente é programado para solicitar a cada objeto que gerencia que execute algumas operações, mas a interface IUnknown não possui funções para essas operações. Em vez disso, essas operações são expressas por meio de outras interfaces. Portanto, o cliente é programado para negociar com objetos para essas interfaces. Especificamente, o cliente chamará QueryInterface para solicitar a um objeto uma interface por meio da qual o cliente pode invocar as operações desejadas.
Como o objeto implementa QueryInterface, ele tem a capacidade de aceitar ou rejeitar a solicitação. Se o objeto aceitar a solicitação do cliente, QueryInterface retornará um novo ponteiro para a interface solicitada para o cliente. Por meio desse ponteiro de interface, o cliente tem acesso aos métodos dessa interface. Se, por outro lado, o objeto rejeitar a solicitação do cliente, QueryInterface retornará um ponteiro nulo , um erro, e o cliente não terá nenhum ponteiro para chamar as funções desejadas. Nesse caso, o cliente deve lidar normalmente com essa possibilidade. Por exemplo, suponha que um cliente tenha um ponteiro para a interface A em um objeto e peça as interfaces B e C. Suponha também que o objeto dê suporte à interface B, mas não dê suporte à interface C. O resultado é que o objeto retorna um ponteiro para B e relata que não há suporte para C.
Um ponto chave é que, quando um objeto rejeita uma chamada para QueryInterface, é impossível para o cliente solicitar que o objeto execute as operações expressas por meio da interface solicitada. Um cliente deve ter um ponteiro de interface para invocar métodos nessa interface. Se o objeto se recusar a fornecer o ponteiro solicitado, o cliente deverá estar preparado para prosseguir sem ele, seja deixando de fazer o que pretendia fazer com esse objeto, seja tentando recorrer a outra interface, talvez menos poderosa. Esse recurso da funcionalidade COM funciona bem em comparação com outros sistemas orientados a objetos nos quais você não pode saber se uma função funcionará até que você chame essa função e, mesmo assim, o tratamento de falhas é incerto. QueryInterface fornece uma maneira confiável e consistente de saber se um objeto dá suporte a uma interface antes de tentar chamar seus métodos.
O método QueryInterface também fornece uma maneira robusta e confiável para um objeto indicar que ele não dá suporte a um determinado contrato. Ou seja, se em uma chamada para QueryInterface alguém perguntar a um objeto "antigo" se ele dá suporte a uma interface "nova" (uma, por exemplo, que foi inventada após o objeto antigo ter sido enviado), o objeto antigo será confiável, sem causar uma falha, responderá "não". A tecnologia que dá suporte a isso é o algoritmo pelo qual os IIDs são alocados. Embora isso possa parecer um ponto pequeno, é extremamente importante para a arquitetura geral do sistema, e a capacidade de consultar elementos herdados sobre novas funcionalidades é, surpreendentemente, um recurso que não está presente na maioria das outras arquiteturas de objeto.
Tópicos relacionados: