请让我知道哪一个好“
考虑我有这样的课程
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;
};
他在这里参考并将其分配给基类对象。
2)
class ShapeContainer
{
public:
ShapeContainer(Shape* pShape) : m_pShape(pShape)
{
}
void Draw()
{
m_pShape->Display();
}
private:
Shape* m_pShape;
};
他在这里拿指针并将其分配给基类对象。
请让我知道哪一个好或何时使用
答案 0 :(得分:7)
必须根据您对对象的要求做出决定。由于您没有包含存储值的选项,我将假设您需要容器来引用外部对象。如果这不是必需的,请考虑使用标准容器:存储对象的副本。
通过使用引用,您可以避免在创建时检查NULL(创建后两个解决方案共享相同的问题:外部对象可能会被破坏,留下悬挂引用和未定义行为)。引用的语义稍微强一些,读取代码的任何人都会立即理解:此容器用于在容器的整个生命周期内保存对该对象的引用,对象生存期在外部进行管理
在它的负面,引用不可重置,一旦你设置了引用它就成为对象的别名,你不能重置它来引用另一个对象。这意味着默认情况下,保存引用的容器不可分配,因为您无法使其引用其他对象。即使您提供自定义赋值运算符,也无法更改引用,并且它将继续引用旧对象。您将无法在容器中提供成员函数来引用其他对象:设置引用后,它将永久设置。
另一方面,指针可以为NULL,因此您可能需要/需要在使用前检查指针的有效性。它们是可重置的,您可以提供操作以使容器在任何时候引用不同的对象,默认情况下容器可以分配。从消极方面来说,指针可以在不同的场景中使用,因此语义不是那么清晰。特别是,您必须在接口上仔细记录容器是否拥有指针的所有权(以及释放内存的责任)。如果你要处理容器内的所有权,那么考虑使用一个智能指针(或者只是制作副本并忘记原件,如果可以的话,这将不易出错)。
答案 1 :(得分:1)
我总是喜欢尽可能使用引用而不是指针。这避免了在使用指针之前必须进行NULL检查,因为引用不能为NULL。顺便说一下,你的shape
类需要一个虚拟析构函数。
答案 2 :(得分:1)
我宁愿说在这种情况下没有好坏,这只是你想要做的事情。 如果不允许用户在向量中存储NULL指针,因为这是一个要求,那么按引用使用。但是如果用户想要为10个对象保留空间但只希望初始化前3个,那么你希望能够存储NULL以便能够区分对象和空白区域。
但如上所述,这是容器的要求。
在你的情况下,我会选择参考。
答案 3 :(得分:0)
如果不需要显式控制容器类中包含的对象的生命周期,我会选择参考方法,并且可以确保传递的引用对象在容器类的生命周期内始终有效。 / p>