Partager via


Règles d’implémentation de QueryInterface

Il existe trois règles main qui régissent l’implémentation de la méthode IUnknown::QueryInterface sur un objet COM :

  • Les objets doivent avoir une identité.
  • L’ensemble d’interfaces sur un objet instance doit être statique.
  • Il doit être possible d’interroger correctement n’importe quelle interface sur un objet à partir de n’importe quelle autre interface.

Les objets doivent avoir une identité

Pour un objet donné instance, un appel à QueryInterface avec IID_IUnknown doit toujours retourner la même valeur de pointeur physique. Cela vous permet d’appeler QueryInterface sur deux interfaces et de comparer les résultats pour déterminer s’ils pointent vers le même instance d’un objet.

L’ensemble d’interfaces sur une instance d’objet doit être statique

L’ensemble d’interfaces accessibles sur un objet via QueryInterface doit être statique et non dynamique. Plus précisément, si QueryInterface retourne S_OK pour un IID donné une fois, il ne doit jamais retourner E_NOINTERFACE sur les appels suivants sur le même objet ; et si QueryInterface retourne E_NOINTERFACE pour un IID donné, les appels ultérieurs pour le même IID sur le même objet ne doivent jamais renvoyer S_OK.

Il doit être possible d’interroger correctement n’importe quelle interface sur un objet à partir d’une autre interface

C’est-à-dire, étant donné le code suivant :

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

Les règles suivantes s’appliquent :

  • Si vous avez un pointeur vers une interface sur un objet, un appel comme le suivant à QueryInterface pour cette même interface doit réussir :

    pA->QueryInterface(IID_IA, ...) 
    
    
  • Si un appel à QueryInterface pour un deuxième pointeur d’interface réussit, un appel à QueryInterface à partir de ce pointeur pour la première interface doit également réussir. Si pB a été obtenu avec succès, les opérations suivantes doivent également réussir :

    pB->QueryInterface(IID_IA, ...) 
    
    
  • Toute interface doit être en mesure d’interroger n’importe quelle autre interface sur un objet . Si le pB a été correctement obtenu et que vous interrogez correctement une troisième interface (IC) à l’aide de ce pointeur, vous devez également être en mesure d’interroger correctement ic à l’aide du premier pointeur, pA. Dans ce cas, la séquence suivante doit réussir :

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

Les implémentations d’interface doivent conserver un compteur de références de pointeur en attente vers toutes les interfaces d’un objet donné. Vous devez utiliser un entier non signé pour le compteur.

Si un client doit savoir que des ressources ont été libérées, il doit utiliser une méthode dans une interface sur l’objet avec une sémantique de niveau supérieur avant d’appeler IUnknown::Release.

Utilisation et implémentation d’IUnknown