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;
};
Related
I am currently trying to learn how to use smart pointers. However while doing some experiments I discovered the following situation for which I could not find a satifying solution:
Imagine you have an object of class A being parent of an object of class B (the child), but both should know each other:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
The question is how can an object of class A pass a std::shared_ptr of itself (this) to its child?
There are solutions for Boost shared pointers (Getting a boost::shared_ptr for this), but how to handle this using the std:: smart pointers?
There is std::enable_shared_from_this just for this purpose. You inherit from it and you can call .shared_from_this() from inside the class. Also, you are creating circular dependencies here that can lead to resource leaks. That can be resolved with the use of std::weak_ptr. So your code might look like this (assuming children rely on existence of parent and not the other way around):
class A;
class B;
class A
: public std::enable_shared_from_this<A>
{
public:
void addChild(std::shared_ptr<B> child)
{
children.push_back(child);
// like this
child->setParent(shared_from_this()); // ok
// ^^^^^^^^^^^^^^^^^^
}
private:
// note weak_ptr
std::list<std::weak_ptr<B>> children;
// ^^^^^^^^
};
class B
{
public:
void setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
}
private:
std::shared_ptr<A> parent;
};
Note however, that calling .shared_from_this() requires that this is owned by std::shared_ptr at the point of call. This means that you cannot create such object on stack anymore, and generally cannot call .shared_from_this() from within a constructor or destructor.
You have several problems in you design, that seem to stem from you misunderstanding of smart pointers.
Smart pointers are used to declare ownership. You are breaking this by declaring that both the parents owns all children, but also that each child own it's parent. Both can't be true.
Also, you are returning a weak pointer in getChild(). By doing so, you are declaring that the caller shouldn't care about the ownership. Now this can be very limiting, but also by doing so, you must make sure that the child in question won't get destroyed while any weak pointers are still held, if you would use a smart pointer, it would get sorted out by itself.
And the final thing. Usually, when you are accepting new entities, you should usually accept raw pointers. Smart pointer can have their own meaning for swapping children between parents, but for general usage, you should accept raw pointers.
I am currently trying to learn how to use smart pointers. However while doing some experiments I discovered the following situation for which I could not find a satifying solution:
Imagine you have an object of class A being parent of an object of class B (the child), but both should know each other:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
The question is how can an object of class A pass a std::shared_ptr of itself (this) to its child?
There are solutions for Boost shared pointers (Getting a boost::shared_ptr for this), but how to handle this using the std:: smart pointers?
There is std::enable_shared_from_this just for this purpose. You inherit from it and you can call .shared_from_this() from inside the class. Also, you are creating circular dependencies here that can lead to resource leaks. That can be resolved with the use of std::weak_ptr. So your code might look like this (assuming children rely on existence of parent and not the other way around):
class A;
class B;
class A
: public std::enable_shared_from_this<A>
{
public:
void addChild(std::shared_ptr<B> child)
{
children.push_back(child);
// like this
child->setParent(shared_from_this()); // ok
// ^^^^^^^^^^^^^^^^^^
}
private:
// note weak_ptr
std::list<std::weak_ptr<B>> children;
// ^^^^^^^^
};
class B
{
public:
void setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
}
private:
std::shared_ptr<A> parent;
};
Note however, that calling .shared_from_this() requires that this is owned by std::shared_ptr at the point of call. This means that you cannot create such object on stack anymore, and generally cannot call .shared_from_this() from within a constructor or destructor.
You have several problems in you design, that seem to stem from you misunderstanding of smart pointers.
Smart pointers are used to declare ownership. You are breaking this by declaring that both the parents owns all children, but also that each child own it's parent. Both can't be true.
Also, you are returning a weak pointer in getChild(). By doing so, you are declaring that the caller shouldn't care about the ownership. Now this can be very limiting, but also by doing so, you must make sure that the child in question won't get destroyed while any weak pointers are still held, if you would use a smart pointer, it would get sorted out by itself.
And the final thing. Usually, when you are accepting new entities, you should usually accept raw pointers. Smart pointer can have their own meaning for swapping children between parents, but for general usage, you should accept raw pointers.
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).
I am currently trying to learn how to use smart pointers. However while doing some experiments I discovered the following situation for which I could not find a satifying solution:
Imagine you have an object of class A being parent of an object of class B (the child), but both should know each other:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
The question is how can an object of class A pass a std::shared_ptr of itself (this) to its child?
There are solutions for Boost shared pointers (Getting a boost::shared_ptr for this), but how to handle this using the std:: smart pointers?
There is std::enable_shared_from_this just for this purpose. You inherit from it and you can call .shared_from_this() from inside the class. Also, you are creating circular dependencies here that can lead to resource leaks. That can be resolved with the use of std::weak_ptr. So your code might look like this (assuming children rely on existence of parent and not the other way around):
class A;
class B;
class A
: public std::enable_shared_from_this<A>
{
public:
void addChild(std::shared_ptr<B> child)
{
children.push_back(child);
// like this
child->setParent(shared_from_this()); // ok
// ^^^^^^^^^^^^^^^^^^
}
private:
// note weak_ptr
std::list<std::weak_ptr<B>> children;
// ^^^^^^^^
};
class B
{
public:
void setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
}
private:
std::shared_ptr<A> parent;
};
Note however, that calling .shared_from_this() requires that this is owned by std::shared_ptr at the point of call. This means that you cannot create such object on stack anymore, and generally cannot call .shared_from_this() from within a constructor or destructor.
You have several problems in you design, that seem to stem from you misunderstanding of smart pointers.
Smart pointers are used to declare ownership. You are breaking this by declaring that both the parents owns all children, but also that each child own it's parent. Both can't be true.
Also, you are returning a weak pointer in getChild(). By doing so, you are declaring that the caller shouldn't care about the ownership. Now this can be very limiting, but also by doing so, you must make sure that the child in question won't get destroyed while any weak pointers are still held, if you would use a smart pointer, it would get sorted out by itself.
And the final thing. Usually, when you are accepting new entities, you should usually accept raw pointers. Smart pointer can have their own meaning for swapping children between parents, but for general usage, you should accept raw pointers.
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).