I've not been able to find a conclusive answer to this so far. When is it safe to call this->
from within an object. And in particular from inside the constructor and destructor.
And also, when using public inheritance. Is it safe to use up and downcasting on the result of the this call?
So for example:
class foo
{
foo():
a(),
b(this->a)//case 1
{
this-> a = 5; //case 2
}
int a;
int b;
};
class bar: public baz
{
bar():
baz(this)//case 3 - assuming baz has a valid constructor
{
}
}
And finally the most unlikely one
foo()
{
if(static_cast<bar*>(this));//case 4
}
Which of the above cases are legal?
Note: I'm aware a lot of the practices above are inadvisable.
There is a good entry on it at the C++ super-faq:
https://isocpp.org/wiki/faq/ctors#using-this-in-ctors
The this pointer is accessible in every non-static member function ...
§9.3.2/1
... where constructors and destructors are member functions ...
§12/1
... which aren't static.
§12.1/4
§12.4/2
Thus,
this
is available in constructors and destructors. But there are limitations (especially with respect to the use ofthis
inside the initializer list).(Note: Inside the constructor / destructor body, the initialization of all subobjects and members is completed and they are accessible; see further down below).
1. Only access object being constructed (or their subobjects) through
this
.§12.1/14
2. Do not call virtual functions that are overriden in a derived class in the base constructor
§12.7/4
3. Do not apply
dynamic_cast
to castthis
into any type other than the type under construction or any base type thereof.§12.7/6
4. Conversion of
this
into base type pointer is only allowed through paths that consist of constructed base types.§12.7/3
Accessing sub-objects and members in the initializer list and the constructor body
In principle you can access constructed / initialized objects from the initializer list, if their initialization takes place before accessing them. The order of initialization is
§12.6.2/10
Within any non-static member function,
this
points to the object that the function was called on. It's safe to use as long as that's a valid object.Within the body of a constructor or destructor, there is a valid object of the class currently being constructed. However, if this is the base sub-object of some derived class, then only the base sub-object is valid at that time; so it's generally not safe to down-cast and try to access members of the derived class. For the same reason, you need to be careful calling virtual functions here, since they are dispatched according to the class being created or destroyed, not the final overrider.
Within the initialiser list of a constructor, you'll need to be careful only to access members that have been initialised; that is, members declared before the one currently being initialised.
Up-casting to a base class is always safe, since base sub-objects are always initialised first.
For the specific examples you just added to the question:
a
has been initialised at that point. Initialisinga
with the value ofb
would be undefined, sinceb
is initialised aftera
.foo
constructor. If there were, then it would depend on what that constructor did with it - whether or not it tried to access members before they were initialised.)
, but dangerous if you tried to use the pointer to access the object.this
does not yet point to a validbar
object (only thefoo
part has been initialised) so accessing members ofbar
could give undefined behaviour. Simply checking whether the pointer is non-null is fine, and will always givetrue
(whether or not you apply a pointless cast).