Sign in to follow this  
mishikel

Using 'this' in base member initializer list

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this