Composition using reference or pointer?
Please let me know which one is good
Consider I have a class like this
class Shape
{
public:
virtual void Display()
{
cout << "Shape::Display()" << endl;
}
};
class Line : public Shape
{
public:
void Display()
{
cout << "Line::Display()" 开发者_开发技巧<< endl;
}
};
class Circle : public Shape
{
public:
void Display()
{
cout << "Circle::Display()" << endl;
}
};
1)
class Container
{
public:
Container(Shape& shape) : m_Shape(shape)
{
}
void Draw()
{
m_Shape.Display();
}
private:
Shape& m_Shape;
};
Here he is taking reference and assigning it to the base class object.
2)
class ShapeContainer
{
public:
ShapeContainer(Shape* pShape) : m_pShape(pShape)
{
}
void Draw()
{
m_pShape->Display();
}
private:
Shape* m_pShape;
};
Here he is taking the pointer and assigning it to the base class object.
Please let me know which one is good or when to use them
The decision has to be taken in terms of what you want to do with your object. Since you are not including the option of storing a value, I will assume that you need the container to refer to an external object. If this is not a requirement, consider using what standard containers do: store a copy of the object.
By using a reference you avoid having to check for NULL on creation (after creation both solutions share the same problem there: the external object might be destroyed, leaving you with a dangling reference and Undefined Behavior). The semantics of a reference are a little stronger, and anyone that reads the code will immediately understand: This container is meant to hold a reference to this object for the whole lifetime of the container, the object lifetime is managed externally.
On the negative side of it, references are not resettable, once you set a reference it becomes an alias to the object, and you cannot reset it to refer to a different object. This means that a container that holds a reference will not be assignable by default as you cannot make it refer to a different object. Even if you provide a custom assignment operator, the reference cannot be changed and it will keep referring to the old object. You will not be able to provide member functions in the container to refer to a different object: once you set a reference, it is set forever.
Pointers on the other hand, can be NULL, so you might want/need to check for validity of the pointer before use. They are resettable, and you can offer operations to have your container refer to a different object at any point, by default the container will be assignable. On the negative side, pointers can be used in different scenarios, so the semantics are not so clear. In particular, you will have to carefully document on the interface whether the container takes ownership of the pointer (and the responsibility to release the memory) or not. If you are going to handle ownership inside the container, then consider using a smart pointer (or else just make a copy and forget the original if you can, which will be less error prone).
I perosnally prefer using references over pointers whenever possible. This avoids having to do a NULL check before using the pointer as references can not be NULL. BTW, your shape
class requires a virtual destructor.
I'd rather say that there is no good or bad in this case, it's just a matter of what you want to do. If the user is not allowed to store NULL pointers in your vector because it's a requirement, then use by reference. But if the user wants to reserve space for 10 objects but only wishes to have the first 3 initialized, then you'd want to be able to store NULL to be able to differentiate between objects and empty space.
But as said, it's a matter of requirement for the container.
In your case i'd choose by reference.
I would go for the reference approach if there is no need to explicitly control the lifetime of the contained object in the container class and you can be sure that the passed reference object is always valid during the lifetime of the container class.
精彩评论