Passing this argument to members in C ++

I want to pass this as an argument to a member variable as follows:

 template<class T> struct fun { fun(T* pointer) : memberPointer(pointer) { } T* memberPointer; }; struct gun { gun() : member(this) { } fun<gun> member; }; 

In Visual Studio, I have the following warning: warning C4355: 'this' : used in base member initializer list

Could you explain why this is wrong? I just store the pointer in the member constructor so that I can use it later to call some gun functions from fun .

+4
source share
4 answers

A potential problem is that this points to an object that has not been fully constructed. For example, if you have this:

 template<class T> struct fun { fun(T* pointer) : memberPointer(pointer) { memberPointer->callMethod(); //this is 2nd to execute } T* memberPointer; }; struct gun { gun() : member(this) //this is 1st to execute { ptr = new char(); // this is 4rd to execute unless earlier UB prevents execution } void callMethod() { printf("%s", ptr); //this is 3rd to execute, you get UB here } fun<gun> member; char* ptr; }; 

you will encounter undefined behavior because you will pass a pointer to an incompletely constructed object, where only a pointer to a fully constructed object should be passed. I intentionally created some crappy code with UB to be more convincing, in real life you will not necessarily have a UB problem, sometimes all objects will be in the correct states, so you will get some very subtle initialization order errors.

This is none of your business. Your business is in order - you do not care that the object is not yet fully constructed. However, you must be careful when changing the code so that you do not fall into the script as described above.

+5
source

This is just a warning. If you want to respect this inside the fun constructor, then you will get access to the uninitialized object. But you are not, you are only saving the pointer, so you can ignore the warning. If you want to disable the warning, add this at the top of your code.

 #pragma warning (disable: 4355) 
+1
source

This is not entirely wrong, but as you pass the pointer, your weapon object may not yet be fully constructed. Therefore, it may happen that you call methods in the base class that rely on the complete construction of your object.

0
source

You want to achieve a static polymorphism that is best handled using a curiously repeating pattern template (CRTP) . In your case, you are almost there:

 template<class Base> struct fun : public Base { void foo() { // call gun function Base::bar(); } }; struct gun : public fun<gun> { void bar() { /*...*/ } }; 
0
source

All Articles