 点蓝色字关注“CurryCoder的程序人生”
点蓝色字关注“CurryCoder的程序人生”
微信公众号:CurryCoder的程序人生
欢迎关注我,一起学习,一起进步!

1.问题的引入
假如你正在给一个应用写一个矩形类,这个矩形由左上角和右下角的顶点坐标表示。为了表示这两个点,我们写一个表示点的类:class Point{
public:
    Point(int x, int y);
    void setX(int newVal);
    void setY(int newVal);
    // ....
};
struct RectData{
    Point ulhc;  // 左上角
    Point lrhc;  // 右下角
};
class Rectangle{
    // ...
private:
    std::shared_ptr pData;  
};class Rectangle{
public:
    // ...
    Point& upperLeft() const {
        return pData->ulhc;
    }
    Point& lowerRight() const {
        return pData->lrhc;
    }
private:
    std::shared_ptr pData;  
};Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2);  // 我们希望它是常对象rec
rec.upperLeft().setX(50);  // upperLeft()的调用者rec能够使用被返回的指向rec内部的Point成员变量的引用来更改成员
// 但是,rec实际上是不可变的,因为它是常对象
3.问题的解决方法
回到上面出现自我矛盾的代码段,如果要解决返回引用会导致数据成员被改变的问题,只需要给函数的返回类型加上一个const。如下面的代码段所示:class Rectangle{
public:
    // ...
    // 现在返回的是const Point&  
    const Point& upperLeft(){
        return pData->ulhc;
    }
    const Point& lowerRight(){
        return pData->lrhc;
    }
private:
    std::shared_ptr pData;  
};class GUIObject{
    // ...
};
const Rectangle boundingBox(const GUIObject& obj);
GUIObject* pgo;
// ...
const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft());
4.总结
(1) 避免返回指向内部成员的"句柄"(包括指针,引用,迭代器)。不返回"句柄"能增强封装性,让const函数成为真正的const,也能减少"野句柄"。觉得好看,请点这里↓↓↓