11
votes

En C ++, initialisez un membre de classe avec «ce» pointeur pendant la construction

J'aimerais créer une classe associée à une autre classe dans une sorte de relation parent-enfant. Pour cela, la classe "enfant" a besoin d'une référence à son parent.

Par exemple: P>

template <typename T>
class TEvent {
    private: T* Owner;
    public: TEvent(T* parent) : Owner(parent) {}
};

class Foo {
    private: TEvent<Foo> Froozle; // see below
};


0 commentaires

5 Réponses :


16
votes

Il est correct d'utiliser ceci dans la liste d'initialisation, tant qu'il n'est pas utilisé pour accéder à des membres qui n'ont pas encore été initialisés.


3 commentaires

Ce qu'il dit. Tant que les objets que vous passez ceci sur "savoir" ne pas la toucher au cours de leur construction (car l'objet Ce fait référence n'est pas entièrement construit à ce moment), Cela va bien, même si certains compilateurs (notamment VC) émettent un avertissement pour cela.


VC ++ est le point clé ici. Ça marche en effet. On dirait que je dois supprimer la "erreur" de force. Merci beaucoup!


Je souhaite que VC ++ n'en émet qu'un avertissement lorsque le membre de "Ceci" à l'intérieur de la CTOR a accédé. BTW, Google :: LogMessage Class dans Google-Glog stocke "Ceci" à elle-même Liste des Mem-Initizer de CTOR à la fin du débogage. Je devais recompiler avec l'avertissement #pragma (4355: désactivé) pour le faire fonctionner dans VC2010.



2
votes

Ceci est censé travailler; En fait,

template<class T>
class Child {
private:
    T *parent;
public:
    Child(T *parent) : parent(parent) {}
};
class Parent {
private:
    Child<Parent> child;
public:
    Parent() : child(this) {}
};


1 commentaires

Le drapeau "Treat Warnings comme des erreurs" Drapeau de la VC et de l'en-tête de documentation MSDN indiquant "Message d'erreur". :) Vous avez absolument raison - ça marche, je ne l'ai tout simplement pas vu. Merci beaucoup!



12
votes

de la norme 12.6.2 / 7 "Initialisation des bases et des membres" (emphase des miennes):

noms dans la liste d'expression d'un Les initialiseurs de Mem sont évalués dans le portée du constructeur pour lequel le L'initialiseur de Mem est spécifié. p>

[Exemple: P>

class X {
    int a;
    int b;
    int i;
    int j;

public:
    const int& r;
    X(int i): r(a), b(i), i(i), j(this->i) {}
};


2 commentaires

Cela signifie-t-il que "ceci" est uniquement autorisé dans la liste de CTors de Mem-Initialiseur ou est-il également autorisé dans le corps de la CTOR? J'ai essayé d'utiliser "ceci" à l'intérieur du corps de CTor en VC2010 ++ plusieurs fois et tout cela compile et fonctionne bien avec un avertissement C4355 désactivé mais simplement parce que cela fonctionne ne signifie pas que je suis autorisé à être autorisé. Jusqu'à présent, je n'ai trouvé aucun dans le DOC Open-Standard qui indique s'il est autorisé à se référer à "Ceci" à l'intérieur du corps de CTOR ou non.


@Davidlee: à l'intérieur du constructeur, Ce pointe sur l'objet en cours de construction (comme dans la liste d'initialistes comme décrit ci-dessus). Vous pouvez définitivement utiliser ce à l'intérieur du corps du constructeur.



1
votes

Si vous souhaitez supprimer l'avertissement, faites-le simplement:

class Foo
{
public:
    Foo() :
    Froozle(get_this())
    {}

private:
    Foo* get_this()
    {
        return this;
    }

    TEvent<Foo> Froozle; // see below
};


1 commentaires

Il h. Pourquoi une méthode appelle-t-elle d'accord, mais une référence directe n'est-elle pas? Compilateur idiot :)



2
votes

Je ne pense pas que cela vous échoue, à moins que vous n'ayez le niveau d'avertissement réglé sur 4 (ou similaire, je suppose Visual Studio) et j'ai activé "Traitement des avertissements comme des erreurs".

Fondamentalement, cet avertissement est un Bonne chose, puisqu'il ne vous laissera pas accidentellement utiliser em> le pointeur code> ce bouton code> lorsque ce qu'il pointe est encore à construire. P>

Cependant, quand Vous savez ce que vous faites partout où ce code> est transmis dans la liste d'initialisation, l'avertissement et l'erreur causés par cela seront ennuyeux. P>

Vous pouvez en débarrasser (à nouveau, en supposant que Visual Studio) en décorant le constructeur (sauf s'il est défini dans la déclaration de classe - vous devez décorer toute la classe): P>

// warning C4355: 'this' : used in base member initializer list
#pragma warning (push)
#pragma warning (disable : 4355)
some_class::some_class()
: ...
{
}
#pragma warning (pop)


0 commentaires