创建一个矩形的类(Rectangle),为保持Rectangle对象较小,可以只在其对象中保存一个指针,用于指向辅助的结构体,定义其范围的点数据存放在辅助的结构体中:
class Point { // 表示点的类
public:
Point(int x, int y);
...
void setX(int newVal);
void setY(int newVal);
...
};
struct RectData { // 矩形的点数据
Point ulhc; // ulhc = " upper left-hand corner"
Point lrhc; // lrhc = " lower right-hand corner"
};
class Rectangle {
...
Point& upperLeft() const { return pData->ulhc; }
Point& lowerRight() const { return pData->lrhc; }
private:
std::shared_ptr<RectData> pData;
};
Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2); // Rec是一个const矩形,范围从
//(0,0)到(100,100)
rec.upperLeft().setX(50); // 现在变为 (50, 0) 到 (100, 100)!
这个设计可以编译,但它是错误的。我们设计的类返回的是一个const修饰的对象,但是我们还是可以修改内部对象的值。
我们可以为函数的返回类型添加const限制来解决这个问题:
class Rectangle {
public:
...
const Point& upperLeft() const { return pData->ulhc; }
const Point& lowerRight() const { return pData->lrhc; }
...
};
即便如此,upperLeft和lowerRight仍然会返回对象内部的句柄,这在其他方面可能会造成问题。特别是,它可能导致悬空(dangling )句柄:指向不再存在的对象的句柄。
#include <iostream>
#include <string>
class Point { // 表示点的类
public:
Point() {};
Point(int x, int y) :_x{x},_y{y}
{
}
void setX(int newVal) {
_x = newVal;
}
void setY(int newVal) {
_y = newVal;
}
std::string toString() const {
std::string result = "(x:" + std::to_string(_x) + "," + std::to_string(_y) + ")";
return result;
}
private:
int _x = 0;
int _y = 0;
};
struct RectData { // 矩形的点数据
Point ulhc; // ulhc = " upper left-hand corner"
Point lrhc; // lrhc = " lower right-hand corner"
};
class Rectangle {
public:
Rectangle(){}
Rectangle(const Point& p1, const Point& p2) {
RectData rectData;
rectData.ulhc = p1;
rectData.lrhc = p2;
pData = std::make_shared<RectData>(rectData);
}
~Rectangle()
{
std::cout << "Rectangle析构函数执行" << std::endl;
}
const Point& upperLeft() const { return pData->ulhc; }
const Point& lowerRight() const { return pData->lrhc; }
void print() const{
std::cout<<pData->ulhc.toString()<<std::endl;
std::cout << pData->lrhc.toString() << std::endl;
}
private:
std::shared_ptr<RectData> pData;
};
Rectangle boudingBox()
{
Point coord1(0, 0);
Point coord2(100, 100);
Rectangle rect(coord1, coord2);
return rect;
}
int main()
{
//Point coord1(0, 0);
//Point coord2(100, 100);
//const Rectangle rec(coord1, coord2);
//rec.print();
//Point right = rec.lowerRight();
//std::cout << "+++++++" << right.toString() << std::endl;
rec.upperLeft().setX(50);
//rec.print();
const Point *right = &(boudingBox().lowerRight());
std::cout << "+++++++" << right->toString() << std::endl;
return 0;
}
避免返回指向对象内部的句柄(引用、指针或迭代器)。遵守这个原则将会增加了封装性,帮助const成员函数保持const行为,并可以尽量避免发生悬空句柄的创建。