考虑如下代码:
class Point {
public:
Point () {}
Point(int x, int y) : mx(x), my(y) {}
void setX(int newVal) {
mx = newVal;
}
void setY(int newVal) {
my = newVal;
}
int xpos() {
return mx;
}
int ypos() {
return my;
}
private:
int mx, my;
};
struct RecDate
{
Point ulhc;
Point urhc;
};
class Rectangle {
// ...
public:
Rectangle(Point cord1, Point cord2) {
pData = std::shared_ptr<RecDate>(new RecDate);
pData.get()->ulhc = cord1;
pData.get()->urhc = cord2;
}
Point& upperLeft() const {
return pData->ulhc;
}
Point& lowerRight() const {
return pData->urhc;
}
private:
std::shared_ptr<RecDate> pData;
};
Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().setX(5);
这样的设计可以通过编译,但是却是错误的,一方面upperLeft
和lowerRight
被声明为const函数,但是另外一方面两个函数都返回references指向private内部数据;解决办法是把两个函数返回类型加上const
:
const Point& upperLeft() const {
return pData->ulhc;
}
const Point& lowerRight() const {
return pData->urhc;
}
虽说上述避免了修改数据情况,但是仍然可能导致以下问题:这些hanles所指东西(的所属对象)不复存在;考虑如下代码:
class GUIOBject {
// ...
};
const Rectangle boundingBox (const GUIOBject& obj) ;
GUIOBject* pgo;
const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft());
对于bounddingBox
的调用获得一个新的,暂时Rectangle
对象,这个对象没有名称,权且成为temp,随后upperLeft
作用于temp身上,返回一个reference
指向temp
的一个内部成分;但是在语句结束之后,boundingBox
的返回值,也就是我们说的temp将被销毁,也最终将导致temp内的Points
析构;最终导致pUpperLeft
指向一个不在存在的对象,也就是说pUpperLeft变成一个空悬,虚吊的了;