Using 'this' in base member initializer list

Started by
6 comments, last by antareus 19 years, 4 months ago

class A;

class B
{
public:
   B(A* a) : parent(a) { ... }
   A* parent;
};

class A
{
public:
   A() : b(new B(this)) { ... }
   boost::shared_ptr< B > b;
};
Writing something like this generates a level 4 warning using MSVC 8: "warning C4355: 'this' : used in base member initializer list". When is it safe to do this, and when is it not safe?
Advertisement
It is safe to do it as long as the object being initialised with this does not try to access a not-yet initialised member (beware of initialistation order - it is the order variables are declared in the class, not the order they are listed in the initialiser list) or use polymorphic behaviour of the non-yet-constructed superclass subclass of this.

See the C++ FAQ Lite.

Edit: I meant subclass, not superclass!

Enigma
You might want to consider getting B to create A and then set a pointer to the instance of A itself. This means you don't have write code like the above that's on the verge of being undefined either now or in the future when you add new features because this will always be ok.
The problem is that this is really bad encapsulation... it creates a "gotcha" where you could screw things up later by changing things within the class of the called object.

Too bad the compiler doesn't actually walk down the call stack to find out if the bad members or methods are actually used during the delicate phase.
-- Single player is masturbation.
Quote:Original post by Pxtl
The problem is that this is really bad encapsulation... it creates a "gotcha" where you could screw things up later by changing things within the class of the called object.

Too bad the compiler doesn't actually walk down the call stack to find out if the bad members or methods are actually used during the delicate phase.


I agree. Rewriting this code for those very reasons.
The specific problem here is the compiler does/can not assume that the constructor B::B(A*) does not access the partially constructed A.

As far as "walking down the call stack", there is no call stack when the code is compiled, and the compiler can predict what code will be executed only in trivial cases. What if B::B(A*) has a conditional statement? How would the compiler know which branch will be executed?
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:Original post by Pxtl
Too bad the compiler doesn't actually walk down the call stack to find out if the bad members or methods are actually used during the delicate phase.


Some do! It's just not required.


...
I'm curious to see an alternative implementation for nested-classes. None come to mind.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
I don't think its bad engineering, its just delicate and should be marked as such. If you need to make links back to objects then thats pretty much the only way to do it. Using a member function opens the code up to the user forgetting to do so. I'll take a compile-time error over a runtime one, thank you.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis

This topic is closed to new replies.

Advertisement