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?
Using 'this' in base member initializer list
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
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.
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.
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?
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?
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.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement