Regole per l'implementazione di QueryInterface

Esistono tre regole principali che regolano l'implementazione del metodo IUnknown:: QueryInterface su un oggetto com:

  • Gli oggetti devono avere Identity.
  • Il set di interfacce in un'istanza di oggetto deve essere statico.
  • Deve essere possibile eseguire una query corretta per qualsiasi interfaccia di un oggetto da qualsiasi altra interfaccia.

Gli oggetti devono avere identità

Per ogni istanza di oggetto specificata, una chiamata a QueryInterface con IID _ IUnknown deve sempre restituire lo stesso valore del puntatore fisico. In questo modo è possibile chiamare QueryInterface su due interfacce e confrontare i risultati per determinare se puntano alla stessa istanza di un oggetto.

Il set di interfacce in un'istanza di oggetto deve essere statico

Il set di interfacce accessibili in un oggetto tramite QueryInterface deve essere statico e non dinamico. In particolare, se QueryInterface restituisce _ un valore OK per un determinato IID una volta, non deve mai restituire E _ nointerface sulle chiamate successive sullo stesso oggetto. Se QueryInterface restituisce e _ nointerface per un determinato IID, le chiamate successive per lo stesso IID sullo stesso oggetto non devono mai restituire S _ OK.

Deve essere possibile eseguire query correttamente per qualsiasi interfaccia di un oggetto da qualsiasi altra interfaccia

Ovvero, dato il codice seguente:

IA * pA = (some function returning an IA *); 
IB * pB = NULL; 
HRESULT   hr; 
hr = pA->QueryInterface(IID_IB, &pB); 
 

si applicano le regole seguenti:

  • Se si dispone di un puntatore a un'interfaccia su un oggetto, una chiamata come la seguente a QueryInterface per la stessa interfaccia deve avere esito positivo:

    pA->QueryInterface(IID_IA, ...) 
    
    
  • Se una chiamata a QueryInterface per un secondo puntatore di interfaccia ha esito positivo, anche una chiamata a QueryInterface da tale puntatore per la prima interfaccia deve avere esito positivo. Se pB è stato ottenuto correttamente, è necessario che venga eseguita anche la seguente operazione:

    pB->QueryInterface(IID_IA, ...) 
    
    
  • Qualsiasi interfaccia deve essere in grado di eseguire query per qualsiasi altra interfaccia in un oggetto. Se pB è stato ottenuto correttamente ed è stata eseguita una query per una terza interfaccia (IC) usando tale puntatore, è necessario anche essere in grado di eseguire query correttamente per IC usando il primo puntatore, pA. In questo caso, la sequenza seguente deve avere esito positivo:

    IC * pC = NULL; 
    hr = pB->QueryInterface(IID_IC, &pC); 
    pA->QueryInterface(IID_IC, ...) 
    
    

Le implementazioni dell'interfaccia devono mantenere un contatore dei riferimenti di puntatore in attesa a tutte le interfacce su un oggetto specificato. Usare un unsigned integer per il contatore.

Se un client deve tenere presente che le risorse sono state liberate, deve usare un metodo in un'interfaccia nell'oggetto con una semantica di livello superiore prima di chiamare IUnknown:: Release.

Uso e implementazione di IUnknown