In C ++, initialize a class element with a 'this' pointer at build time

I would like to create a class associated with another class in some way the relationship between parents and children. For this, the "child" class needs a reference to it by the parent.

For example:

template <typename T> class TEvent { private: T* Owner; public: TEvent(T* parent) : Owner(parent) {} }; class Foo { private: TEvent<Foo> Froozle; // see below }; 

Now the problem is that I cannot initialize the Froozle instance directly or use the instanciation list of the Foo constructor, because this links are not allowed there. Besides adding another setParent(T*) method (which I don't like too much because it means I have to leave the TEvent<> instance in an invalid state), is there a way to achieve this?

+6
c ++ initialization this class
Oct 23 '10 at 21:28
source share
5 answers

It is good to use this in the initialization list if it is not used to access elements that have not yet been initialized.

+11
Oct 23 2018-10-23
source share

From the standard 12.6.2 / 7 "Initialization of bases and members" (my attention):

Names in the mem-initializer expression list are evaluated against the constructor for which mem-initializer is specified.

[Example:

 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) {} }; 

initializes X::r to refer to X::a , initializes X::b with the value of constructor parameter i , initializes X::i with the value of constructor i and initializes X::j with the value of X::i ; this happens every time a class X object is created. ]

[Note: since the mem initializer is evaluated as part of the constructor, the this pointer can be used in the list of expressions the mem initializer to reference the object is initialized. ]

+10
Oct 23 2018-10-10
source share

This should work; actually,

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

compiles for me with both g ++ 4.4.5 and clang ++ 2.8.

What does not suit you?

+1
Oct 23 '10 at 21:37
source share

If you want to suppress the warning, just do the following:

 class Foo { public: Foo() : Froozle(get_this()) {} private: Foo* get_this() { return this; } TEvent<Foo> Froozle; // see below }; 

Not enough indirection to stop him.

+1
Oct 23 '10 at 21:59
source share

I don’t think this will work for you if you haven’t set warning level 4 (or similar, I assume Visual Studio) and turned on “handle warnings as errors”.

Basically, this warning is a “Good Thing”, as it will not allow you to accidentally use the this pointer when what it points to is not yet built.

However, when you know what you are doing, where this is passed in the initialization list, the warning and error caused by this will be annoying.

You can get rid of it (again, by accepting Visual Studio) by decorating the constructor (if it is not defined in the class declaration), then you should decorate the whole class):

 // warning C4355: 'this' : used in base member initializer list #pragma warning (push) #pragma warning (disable : 4355) some_class::some_class() : ... { } #pragma warning (pop) 
+1
Oct 23 '10 at 22:01
source share



All Articles