I have two classes with a parent-child relationship (the Parent class "has-a" Child class), and the Child class has a pointer back to the Parent. It would be nice to initialize the parent pointer upon construction of the child, as follows:
class Child;
class Parent;
class Child
{
public:
Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(this) {};
private:
Child child;
}
Now, I know people recommend not using this in initialization list, and C++ FAQ says I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent's constructor. My questions are:
Is the parent this pointer well-defined when the Child object is being created?
If so, why is it considered bad practice to use it as above?
Thanks,
Boaz
EDIT: Thanks Timbo, it is indeed a duplicate (huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :
class Child
{
public:
Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(*this) {};
private:
Child child;
}
Yes. It's safe to use this pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child can store the this pointer of Parent for later use!
The parent this pointer, in "pointer terms", is well-defined (otherwise how would the parent constructor know on which instance is it operating?), but:
the fields that are declared after the Child object aren't initialized yet;
the code in the constructor hasn't run yet;
also, the usual warnings about using virtual members from the constructor apply1.
So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).
Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.
I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.
The behaviour is well-defined so long as you don't attempt to dereference the pointer until after the Parent object has been completely constructed (as #Sergey says in a comment below, if the object being constructed is actually derived from Parent, then all of its constructors must have completed).
Related
I am having trouble with RobotControl class members. The UML specifies the relation between RobotControl’s position and RangeSensor as composition. Doesn't using pointers for them, make them aggregation? How should I declare - create these members with respect to UML, or has UML mistaken?
Pointers in C++ can be used for both aggregation and composition. The distinction is, as correctly noted by Douglas, whether the lifetime of the objects is interconnected. In other words: Is the child destroyed when the parent is destroyed? The answer Yes stands for composition, No for aggregation.
How do we distinguish these cases in a C++ code?
Pointers in C++ can mean the ownership of another (dynamically created) object, or just refer to an object owned by someone else. Let’s show the differences in examples. I’ll explain why pointers can be useful for each type of relationship.
Aggregation with a pointer
In this case, it is fine to only forward-declare the class Child before class Parent declaration and the child member can be set and re-set during the lifetime of the Parent.
class Child;
class Parent
{
public:
Parent(Child* ch) : child(ch) {}
Parent() : child(NULL) {}
void setChild(Child* ch) { child = ch; }
private:
Child* child;
};
Composition with a pointer
The longest example shows that we can dynamically create and destroy the child using a pointer. The child’s lifetime is strongly interconnected with the Parent. However, we can still swap children during the lifetime of the Parent thanks to pointers. This solution also allows to only forward-declare class Child in the header file unlike the alternative below.
// --- header file
class Child;
class Parent
{
public:
Parent();
~Parent();
void renewChild();
private:
Child* child;
};
// --- source file
#include "child.h"
Parent::Parent()
: child(new Child)
{
}
Parent::~Parent()
{
delete child;
}
void Parent::renewChild()
{
delete child;
child = new Child;
}
Disclaimer
This example is a subject to the Rule of three/five/zero. I am intentionally letting the implementation of missing recommended methods up to the user, keeping this answer dialect-agnostic and as simple as possible.
Composition without pointers
Instead of writing constructor and destructor manually, you can just declare child in the class declaration and let the compiler to do the construction and destruction for you. This is valid as long as the class Child’s constructor requires no parameters (otherwise you’d need to write class Parent’s constructor manually) and the class Child is fully declared before the declaration of class Parent.
#include "child.h"
class Parent
{
private:
Child child;
};
Aggregation without pointers
To be complete, the alternative to using pointers for aggregation is using a reference. However, this prevents swapping children during the lifetime of the Parent object.
class Child;
class Parent
{
public:
Parent(Child& ch) : child(ch) {}
private:
Child& child;
};
(Note that this is an oversimplification of my actual design.)
Given the following:
class CParentA;
class C_Child
public:
C_Child(C_ParentB* parent) : m_parent(parent){};
virtual ~C_Child();
CParentB* m_parent;
};
class C_ParentA : public C_Child
{
public:
C_ParentA(C_GrandParent *gp) : C_Child(gp){};
virtual ~C_ParentA(){};
}
class C_ParentB
{
public:
C_ParentB(){};
virtual ~C_ParentB(){};
void foo(){};
}
class C_GrandParent : public C_ParentB, public C_ParentA
{
public:
C_GrandParent() : C_ParentA(this){};
virtual ~C_GrandParent();
}
main()
{
C_GrandParent gp;
gp.m_parent->foo();
}
It seems that parentB's pointer, sent to the child's constructor, isn't valid yet when the grandparent is created. I had thought that, even if the parent wasn't fully constructed, it's pointer (this) would still be valid. I've also tried having ParentB be a pointer stored in the grandparent, and the object dynamically created in the grandparent constructor. But that apparently has the same outcome.
FWIW: the goal of this: grandparent has many parents, some of them with children. One child may need access to another child or a parent (uncle/cousin). I had thought that having them all under one patriarch would handle much of the inter-relationships between family members. While that is the case, setting the appropriate pointers seems to be the problem.
First, is is not clear what you are asking, so I am just trying to speculate. You present a design that is not working so you must be asking for alternatives, but you give no information on what you are trying to do.
Second, when class A derives a class B we usually say B is the base or parent and A is the derived or child. You use the opposite terminology and this is very confusing.
Now, I only assume that CParentB* m_parent; in C_Child is supposed to refer to the same C_Child object, viewed as CParentB. You don't need to store a pointer for this. Given a C_Child& r reference or C_Child* p pointer, you can simply say respectively
dynamic_cast<CParentB&>(r)
dynamic_cast<CParentB*>(p)
Both will fail in different ways if r,p do not refer to a CParentB object. dynamic_cast lets you navigate the entire class hierarchy and check at run time if a cast is valid. If the classes are not polymorphic, you can use static_cast instead.
In any case, keep in mind that before any object of a derived class is fully constructed, its bases need to constructed first. So before that, avoid playing in any way with the partially constructed object, like calling its methods especially virtual ones.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
Consider the following situation - pair of Parent and Child classes. Parent constructor requires a Child class to be instantiated, because it has to initialize it in a special way. Both Parent and Child may be derived, such that DerivedParent uses DerivedChild.
There's a problem, however - because in Parent::ctor call from DerivedParent::ctor, base class should have an instance of DerivedChild instead of Child. But that would require calling a virtual method some way, what is prohibited. I'm talking about something like this:
class Child
{
public:
virtual std::string ToString() { return "Child"; }
};
class DerivedChild : public Child
{
public:
std::string ToString() { return "DerivedChild"; }
};
class Parent
{
protected:
Child * child;
virtual Child * CreateChild() { return new Child(); }
public:
Parent() { child = CreateChild(); }
Child * GetChild() { return child; }
};
class DerivedParent : public Parent
{
protected:
Child * CreateChild() { return new DerivedChild(); }
};
int main(int argc, char * argv[])
{
DerivedParent parent;
printf("%s\n", parent.GetChild()->ToString().c_str());
getchar();
return 0;
}
Let's get a real-world example. Suppose, that I want to write wrapper for WinApi's windows. The base Control class should register class and instantiate a window (eg. RegisterClassEx and CreateWindowEx), to properly set it up (for example register class in such way, that window structure has additional data for class instance; set up generic WndProc for all Controls; put reference to this by SetWindowLongPtr etc.)
On the other hand, derived class should be able to specify styles and extended styles, class name for window etc.
If constructing instance of window in the Control's constructor is a contract to be fulfilled, I see no other solution than to use VMs in ctor (what won't work).
Possible workarounds:
Use static polymorphism (eg. class Derived : public Base), but it will not work, if one wants to derive from Derived;
Pass a lambda from derived to base ctor if it is possible - it will work, but it's a total hardcore solution;
Pass a ton of parameters from derived to base ctor - it shall work, but won't be neither elegant, nor easy to use.
I personally don't like neither of them. Out of curiosity, I checked, how the problem is solved in Delphi's VCL, and you know what, base class calls CreateParams, which is virtual (Delphi allows such calls and guarantees, that they are safe - class fields are initialized to 0 upon creating).
How can one overcome this language restriction?
Edit: In response to answers:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
It will work, but it's not an option - quoting the famous C++ FAQ:
The first variation is simplest initially, though the code that actually wants to create objects requires a tiny bit of programmer self-discipline, which in practice means you're doomed. Seriously, if there are only one or two places that actually create objects of this hierarchy, the programmer self-discipline is quite localized and shouldn't cause problems.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
It's not an option, because it will work only once, for base class and its immediate descendant.
Make the child pointer a constructor argument, for example to a factory function.
This is, so far, the best solution - injecting code into base ctor. In my case, I won't even need to do it, because I can just parametrize base ctor and pass values from the descendant. But it will actually work.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
Yea, but it has some drawbacks:
Someone, who derives from my classes may publish his ctor and bypass the security measures;
It would prevent one from using references, one would have to use smart pointers.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
No, calling a virtual method in the constructor dispatches to the most-derived complete object, which is the one under construction. It's not prohibited, it's well-defined and it does the only thing that would make sense.
A C++ base class is not allowed to know the identity of the most derived object, for better or worse. Under the model, the derived object doesn't start to exist until after the base constructors have run, so there's nothing to get type information about.
Some alternatives in your case are:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
Make the child pointer a constructor argument, for example to a factory function.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
When using interfaces in c++; You have your abstract (parent) class. Then you have the child class which inherits from the parent class and implements the pure virtual functions.
When another class uses the (child) interface, what is the point in the abstract class at this point? If you try to use the parent type in a function, i.e returning the type Parent, you get compiler errors (presumably because the compiler doesn't know how much memory to allocate).
Can anyone tell me how to do the above?
i.e
Parent = Shape.
Child = Rectangle.
Thrid class which contains method which returns the type Shape?
Thanks in advance for any help/information.
A big advantage is that all children share the same interface. If you have a second child inheriting from the parent (Child = Circle), then regardless of the specific subclass, both of them can use the same functions.
Imagine then that you have a vector with pointers to shapes (vector < Shape* >), then it doesn't matter which shapes you have in the vector, if your base class Shape has a virtual method Draw(), you can use that method from each element of the vector without explicit knowledge how that Draw method is implemented.
You cannot instantiate an abstract class. Period. If you have a child that you want to access through a base-class interface, then you must access the child through a pointer or reference to the base class.
class A
{
public:
virtual void doit() = 0;
}
class B : public A
{
public:
virtual void doit()
{std::cout << "Hi.";}
}
...later, in main
A *a = new B;
a->doit(); //this calls B's implementation.
If you don't know why this is handy, you should research the term "polymorphism."
I think you are returning the objects on the stack, which doesn't work because you simply cannot instantiate abstract types:
Parent Child::foo() {
return Child(12);
}
That means, the compiler reserves (or rather, would reserve) the space for a Parent. And also try to copy construct Parents when calling foo.
What you probably meant was this:
Parent* Child::foo() {
return new Child(12); // actually you should really be using a shared pointer here, but that's a different story
}
This works, because the pointer to Parent and the pointer to Child have the size and alignment.
You can even directly return a Child because of co-variance. C++ allows you to implement Parent* Parent::foo(); as Child* Child::foo(); if Child inherits from Parent.
I have two classes with a parent-child relationship (the Parent class "has-a" Child class), and the Child class has a pointer back to the Parent. It would be nice to initialize the parent pointer upon construction of the child, as follows:
class Child;
class Parent;
class Child
{
public:
Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(this) {};
private:
Child child;
}
Now, I know people recommend not using this in initialization list, and C++ FAQ says I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent's constructor. My questions are:
Is the parent this pointer well-defined when the Child object is being created?
If so, why is it considered bad practice to use it as above?
Thanks,
Boaz
EDIT: Thanks Timbo, it is indeed a duplicate (huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :
class Child
{
public:
Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(*this) {};
private:
Child child;
}
Yes. It's safe to use this pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child can store the this pointer of Parent for later use!
The parent this pointer, in "pointer terms", is well-defined (otherwise how would the parent constructor know on which instance is it operating?), but:
the fields that are declared after the Child object aren't initialized yet;
the code in the constructor hasn't run yet;
also, the usual warnings about using virtual members from the constructor apply1.
So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).
Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.
I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.
The behaviour is well-defined so long as you don't attempt to dereference the pointer until after the Parent object has been completely constructed (as #Sergey says in a comment below, if the object being constructed is actually derived from Parent, then all of its constructors must have completed).