CComObjectRootEx, classe

Cette classe fournit des méthodes pour gérer la gestion du nombre de références d’objets pour les objets non agrégés et non agrégés.

Syntaxe

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Paramètres

ThreadModel
Classe dont les méthodes implémentent le modèle de threading souhaité. Vous pouvez choisir explicitement le modèle de thread en définissant ThreadModel sur CComSingleThreadModel, CComMultiThreadModel ou CComMultiThreadModelNoCS. Vous pouvez accepter le modèle de thread par défaut du serveur en définissant ThreadModel sur CComObjectThreadModel ou CComGlobalsThreadModel.

Membres

Méthodes

Fonction Description
CComObjectRootEx Constructeur.
InternalAddRef Incrémente le nombre de références pour un objet non agrégé.
InternalRelease Décrémente le nombre de références pour un objet non agrégé.
Verrouiller Si le modèle de thread est multithread, obtient la propriété d’un objet de section critique.
Déverrouiller Si le modèle de thread est multithread, libère la propriété d’un objet de section critique.

CComObjectRootBase, méthodes

Fonction Description
FinalConstruct Remplacez dans votre classe pour effectuer toute initialisation requise par votre objet.
FinalRelease Remplacez dans votre classe pour effectuer tout nettoyage requis par votre objet.
OuterAddRef Incrémente le nombre de références pour un objet agrégé.
OuterQueryInterface Délégués à l’extérieur IUnknown d’un objet agrégé.
OuterRelease Décrémente le nombre de références d’un objet agrégé.

Fonctions statiques

Fonction Description
InternalQueryInterface Délégués à l’objet IUnknown non agrégé.
ObjectMain Appelé lors de l’initialisation et de l’arrêt du module pour les classes dérivées répertoriées dans le mappage d’objets.

Données membres

Membre de données Description
m_dwRef Avec m_pOuterUnknown, partie d’une union. Utilisé lorsque l’objet n’est pas agrégé pour contenir le nombre de références et AddRef Release.
m_pOuterUnknown Avec m_dwRef, partie d’une union. Utilisé lorsque l’objet est agrégé pour contenir un pointeur vers l’inconnu externe.

Notes

CComObjectRootEx gère la gestion des nombres de références d’objets pour les objets non agrégés et non agrégés. Il contient le nombre de références d’objet si votre objet n’est pas agrégé et contient le pointeur vers l’inconnu externe si votre objet est agrégé. Pour les objets agrégés, CComObjectRootEx les méthodes peuvent être utilisées pour gérer l’échec de la construction de l’objet interne et pour protéger l’objet externe contre la suppression lorsque les interfaces internes sont libérées ou que l’objet interne est supprimé.

Une classe qui implémente un serveur COM doit hériter ou CComObjectRoot CComObjectRootEx .

Si votre définition de classe spécifie la macro DECLARE_POLY_AGGREGATABLE , ATL crée une instance de CComPolyObject<CYourClass> quand IClassFactory::CreateInstance elle est appelée. Lors de la création, la valeur de l’inconnu externe est vérifiée. S’il s’agit de NULL, IUnknown est implémenté pour un objet non agrégé. Si l’inconnu externe n’est pas NULL, IUnknown est implémenté pour un objet agrégé.

Si votre classe ne spécifie pas la macro DECLARE_POLY_AGGREGATABLE, ATL crée une instance d’objets CAggComObject<CYourClass> agrégés ou une instance d’objets CComObject<CYourClass> non agrégés.

L’avantage de l’utilisation CComPolyObject est que vous évitez d’avoir à la fois CComAggObject et CComObject dans votre module pour gérer les cas agrégés et non agrégés. Un objet unique CComPolyObject gère les deux cas. Par conséquent, une seule copie de la table virtuelle et une copie des fonctions existent dans votre module. Si votre vtable est volumineux, cela peut réduire considérablement la taille de votre module. Toutefois, si votre vtable est petit, l’utilisation CComPolyObject peut entraîner une taille de module légèrement plus grande, car elle n’est pas optimisée pour un objet agrégé ou non agrégé, comme c’est le cas CComAggObject et CComObject.

Si votre objet est agrégé, IUnknown est implémenté par CComAggObject ou CComPolyObject. Ces classes délèguent QueryInterface, AddRefet Release appellent ' CComObjectRootExs OuterQueryInterface, OuterAddRefet OuterRelease pour transférer vers l’inconnu externe. En règle générale, vous remplacez CComObjectRootEx::FinalConstruct dans votre classe pour créer des objets agrégés et remplacer CComObjectRootEx::FinalRelease pour libérer tous les objets agrégés.

Si votre objet n’est pas agrégé, IUnknown est implémenté par CComObject ou CComPolyObject. Dans ce cas, les appels à QueryInterface, AddRefet Release sont délégués à CComObjectRootEx's InternalQueryInterface, InternalAddRefet InternalRelease pour effectuer les opérations réelles.

Spécifications

En-tête : atlcom.h

CComObjectRootEx ::CComObjectRootEx

Le constructeur initialise le nombre de références à 0.

CComObjectRootEx();

CComObjectRootEx ::FinalConstruct

Vous pouvez remplacer cette méthode dans votre classe dérivée pour effectuer toute initialisation requise pour votre objet.

HRESULT FinalConstruct();

Valeur de retour

RetourneZ S_OK sur la réussite ou l’une des valeurs HRESULT d’erreur standard.

Notes

Par défaut, CComObjectRootEx::FinalConstruct retourne simplement S_OK.

Il existe des avantages pour effectuer l’initialisation au FinalConstruct lieu du constructeur de votre classe :

  • Vous ne pouvez pas retourner un code d’état à partir d’un constructeur, mais vous pouvez renvoyer un HRESULT au moyen de la valeur de retour.FinalConstruct Lorsque des objets de votre classe sont créés à l’aide de la fabrique de classes standard fournie par ATL, cette valeur de retour est propagée au client COM, ce qui vous permet de leur fournir des informations d’erreur détaillées.

  • Vous ne pouvez pas appeler des fonctions virtuelles par le biais du mécanisme de fonction virtuelle à partir du constructeur d’une classe. L’appel d’une fonction virtuelle à partir du constructeur d’une classe entraîne un appel résolu statiquement à la fonction telle qu’elle est définie à ce stade dans la hiérarchie d’héritage. Les appels à des fonctions virtuelles pures entraînent des erreurs d’éditeur de liens.

    Votre classe n’est pas la classe la plus dérivée de la hiérarchie d’héritage. Elle s’appuie sur une classe dérivée fournie par ATL pour fournir certaines de ses fonctionnalités. Il existe une bonne chance que votre initialisation ait besoin d’utiliser les fonctionnalités fournies par cette classe (c’est certainement vrai lorsque les objets de votre classe doivent agréger d’autres objets), mais le constructeur de votre classe n’a aucun moyen d’accéder à ces fonctionnalités. Le code de construction de votre classe est exécuté avant que la classe la plus dérivée soit entièrement construite.

    Toutefois, FinalConstruct elle est appelée immédiatement après la construction de la classe la plus dérivée, ce qui vous permet d’appeler des fonctions virtuelles et d’utiliser l’implémentation de comptage de référence fournie par ATL.

Exemple

En règle générale, remplacez cette méthode dans la classe dérivée pour CComObjectRootEx créer des objets agrégés. Par exemple :

class ATL_NO_VTABLE CMyAggObject :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CMyAggObject, &CLSID_MyAggObject>,
   public IDispatchImpl<IMyAggObject, &IID_IMyAggObject, &LIBID_NVC_ATL_COMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
   DECLARE_GET_CONTROLLING_UNKNOWN()
   HRESULT FinalConstruct()
   {
      return CoCreateInstance(CLSID_MyCustomClass, GetControllingUnknown(), 
         CLSCTX_ALL, IID_IUnknown, (void**)&m_pMyCustomClass);
   }

   IMyCustomClass* m_pMyCustomClass;

   // Remainder of class declaration omitted.

Si la construction échoue, vous pouvez retourner une erreur. Vous pouvez également utiliser la macro DECLARE_PROTECT_FINAL_CONSTRUCT pour protéger votre objet externe de la suppression si, pendant la création, l’objet agrégé interne incrémente le nombre de références, puis décrémente le nombre à 0.

Voici un moyen classique de créer un agrégat :

  • Ajoutez un IUnknown pointeur à votre objet de classe et initialisez-le sur NULL dans le constructeur.

  • Remplacez FinalConstruct la création de l’agrégat.

  • Utilisez le IUnknown pointeur que vous avez défini comme paramètre pour la macro COM_INTERFACE_ENTRY_AGGREGATE .

  • Remplacez FinalRelease le pointeur pour libérer le IUnknown pointeur.

CComObjectRootEx ::FinalRelease

Vous pouvez remplacer cette méthode dans votre classe dérivée pour effectuer tout nettoyage requis pour votre objet.

void FinalRelease();

Notes

Par défaut, CComObjectRootEx::FinalRelease ne fait rien.

L’exécution d’un nettoyage est FinalRelease préférable à l’ajout de code au destructeur de votre classe, car l’objet est toujours entièrement construit au point où FinalRelease il est appelé. Cela vous permet d’accéder en toute sécurité aux méthodes fournies par la classe la plus dérivée. Cela est particulièrement important pour libérer tous les objets agrégés avant la suppression.

CComObjectRootEx ::InternalAddRef

Incrémente le nombre de références d’un objet non agrégé de 1.

ULONG InternalAddRef();

Valeur de retour

Valeur qui peut être utile pour les diagnostics et les tests.

Notes

Si le modèle de thread est multithread, InterlockedIncrement il est utilisé pour empêcher plusieurs threads de modifier le nombre de références en même temps.

CComObjectRootEx ::InternalQueryInterface

Récupère un pointeur vers l'interface demandée.

static HRESULT InternalQueryInterface(
    void* pThis,
    const _ATL_INTMAP_ENTRY* pEntries,
    REFIID iid,
    void** ppvObject);

Paramètres

pThis
[in] Pointeur vers l’objet qui contient la carte COM des interfaces exposées à QueryInterface.

pEntries
[in] Pointeur vers la _ATL_INTMAP_ENTRY structure qui accède à une carte d’interfaces disponibles.

iid
[in] GUID de l’interface demandée.

ppvObject
[out] Pointeur vers le pointeur d’interface spécifié dans iid ou NULL si l’interface est introuvable.

Valeur de retour

Une des valeurs HRESULT standard.

Notes

InternalQueryInterface gère seulement des interfaces dans le tableau de mappage COM. Si votre objet est agrégé, InternalQueryInterface ne délègue pas à l’inconnu externe. Vous pouvez entrer des interfaces dans la table de mappage COM avec la macro COM_INTERFACE_ENTRY ou l’une de ses variantes.

CComObjectRootEx ::InternalRelease

Décrémente le nombre de références d’un objet non agrégé par 1.

ULONG InternalRelease();

Valeur de retour

Dans les builds non debug et de débogage, cette fonction retourne une valeur qui peut être utile pour les diagnostics ou les tests. La valeur exacte retournée dépend de nombreux facteurs tels que le système d’exploitation utilisé et peut, ou non, être le nombre de références.

Notes

Si le modèle de thread est multithread, InterlockedDecrement il est utilisé pour empêcher plusieurs threads de modifier le nombre de références en même temps.

CComObjectRootEx ::Lock

Si le modèle de thread est multithread, cette méthode appelle la fonction d’API Win32 EnterCriticalSection, qui attend que le thread puisse prendre possession de l’objet de section critique obtenu via un membre de données privé.

void Lock();

Notes

Une fois l’exécution du code protégé terminée, le thread doit appeler Unlock pour libérer la propriété de la section critique.

Si le modèle de thread est monothread, cette méthode ne fait rien.

CComObjectRootEx ::m_dwRef

Partie d’une union qui accède à quatre octets de mémoire.

long m_dwRef;

Notes

Avec m_pOuterUnknown, partie d’une union :

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Si l’objet n’est pas agrégé, le nombre de références accessible AddRef et Release est stocké dans m_dwRef. Si l’objet est agrégé, le pointeur vers l’inconnu externe est stocké dans m_pOuterUnknown.

CComObjectRootEx ::m_pOuterUnknown

Partie d’une union qui accède à quatre octets de mémoire.

IUnknown*
    m_pOuterUnknown;

Notes

Avec m_dwRef, partie d’une union :

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Si l’objet est agrégé, le pointeur vers l’inconnu externe est stocké dans m_pOuterUnknown. Si l’objet n’est pas agrégé, le nombre de références accessible AddRef et Release est stocké dans m_dwRef.

CComObjectRootEx ::ObjectMain

Pour chaque classe répertoriée dans le mappage d’objets, cette fonction est appelée une fois lorsque le module est initialisé et à nouveau lorsqu’il est arrêté.

static void WINAPI ObjectMain(bool bStarting);

Paramètres

bStarting
[out] La valeur est TRUE si la classe est initialisée ; sinon FALSE.

Notes

La valeur du paramètre bStarting indique si le module est initialisé ou arrêté. L’implémentation par défaut ne ObjectMain fait rien, mais vous pouvez remplacer cette fonction dans votre classe pour initialiser ou nettoyer les ressources que vous souhaitez allouer pour la classe. Notez qu’elle ObjectMain est appelée avant que toutes les instances de la classe soient demandées.

ObjectMain est appelé à partir du point d’entrée de la DLL, de sorte que le type d’opération que la fonction de point d’entrée peut effectuer est restreint. Pour plus d’informations sur ces restrictions, consultez les DLL et le comportement de la bibliothèque d’exécution Visual C++ et DllMain.

Exemple

class ATL_NO_VTABLE CMyApp :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CMyApp, &CLSID_MyApp>,
   public IMyApp
{
public:
   CMyApp()
   {
   }

   static void WINAPI ObjectMain(bool bStarting)
   {
      if (bStarting)
         ;// Perform custom initialization routines
      else
         ;// Perform custom termination routines
   }

   // Remainder of class declaration omitted.

CComObjectRootEx ::OuterAddRef

Incrémente le nombre de références de l’inconnu externe d’une agrégation.

ULONG OuterAddRef();

Valeur de retour

Valeur qui peut être utile pour les diagnostics et les tests.

CComObjectRootEx ::OuterQueryInterface

Récupère un pointeur indirect vers l’interface demandée.

HRESULT OuterQueryInterface(REFIID iid, void** ppvObject);

Paramètres

iid
[in] GUID de l’interface demandée.

ppvObject
[out] Pointeur vers le pointeur d’interface spécifié dans iid ou NULL si l’agrégation ne prend pas en charge l’interface.

Valeur de retour

Une des valeurs HRESULT standard.

CComObjectRootEx ::OuterRelease

Décrémente le nombre de références de l’inconnu externe d’une agrégation.

ULONG OuterRelease();

Valeur de retour

Dans les builds non debug, retourne toujours 0. Dans les builds de débogage, retourne une valeur qui peut être utile pour les diagnostics ou les tests.

CComObjectRootEx ::Unlock

Si le modèle de thread est multithread, cette méthode appelle la fonction API Win32 LeaveCriticalSection, qui libère la propriété de l’objet de section critique obtenu via un membre de données privé.

void Unlock();

Notes

Pour obtenir la propriété, le thread doit appeler Lock. Chaque appel nécessite Lock un appel correspondant pour Unlock libérer la propriété de la section critique.

Si le modèle de thread est monothread, cette méthode ne fait rien.

Voir aussi

CComAggObject, classe
CComObject, classe
CComPolyObject, classe
Vue d’ensemble de la classe