Effective C++——条款28(第5章)

条款28:    避免返回handles指向对象内部成分

Avoid returning "handles" to object internals

    假设程序涉及矩形,每个矩形由其左上角和右下角表示.为了让Rectangle对象尽可能小,可能会决定不把定义矩形的这些点放在Rectangle对象内,而是放在一个辅助的 struct 内再让Rectangle去指它:
class Point {
public:
    Point(int x, int y);
    ...
    void setX(int newVal);
    void setY(int newVal);
    ...
};
struct RectData {
    Point ulhc;            // upper left-hand comer
    Point lrhc;            // lower right-hand comer
};
class Rectangle {
    ...
private:
    std::tr1::shared_ptr<RectData> pData;
};
    这个 class 还提供了upperLeft函数和lowerRight函数,Point是个用户自定义类型,所以根据 条款20的忠告(以by reference方式传递用户自定义类型往往比by value方式传递更高效),这些函数于是范虎reference,代表底层的Point对象:
class Rectangle {
public:
    ...
    Point& upperLeft() const { return pData->ulhc; }
    Point& lowerRight() const { return pData->lrhc; }
    ...
};
    这样的设计可通过编译,但确实错误的.实际上它是自我矛盾的. 一方面upperLeft和lowerRight被声明为 const 成员函数,因为它们的目的只是为了提供客户一个得知Rectangle相关坐标点的方法,而不是让客户修改Rectangle(详见 条款3) .另一方面这两个函数却返回reference指向 private 内部数据, 调用者于是 可通过这些reference更改内部数据!
    这立刻给出 两个教训: 第一,成员变量的封装性最多只等于"返回其reference"的函数的访问级别.本例中虽然ulhc和lrhc都 被声明为 private,但它们实际上却是 public,因为 public 函数upperLeft和lowerRight传出了它们的reference. 第二,如果 const 成员函数传出一个reference,后者所指的数据与对象自身有关联,而它又被存储在对象外,那么这个函数的 调用者可以修改该那笔数据.这正是bitwise constness的一个附带结果,详见 条款3.
    上述所说的每件事都是由于"成员函数返回reference".如果它们返回的是指针或迭代器,相同的情况还是发生,原因也相同. Reference,指针和迭代器统统都是所谓的handles(号码牌,用来取得某个对象),而返回一个"代表对象内部数据"的handle,随之而来的便是"降低对象封装性"的风险.
    在前两个函数身上的 问题可以轻松去除,只要对它们的返回类型加上 const 即可:
class Rectangle {
public:
    ...
    const Point& upperLeft() const { return pData->ulhc; }
    const Point& lowerRigth() const { return pData->lrhc; }
    ...
};
    有了这样的改变,客户可以读取矩形的Point,但不能修改它们.
    即使如此,函数如果"返回一个handle代表对象内部成分"还是危险的,可能变为悬挂的(dangling).原因是,有个handle被传出去,一旦如此就有"handle比其所指对象更长寿"的风险(可能对象被析构了,但handle还存在(它指向对象内部)).
     注意:
    避免返回handle(包括reference,指针,迭代器)指向对象内部.遵守这个条款可增加封装性,帮助 const 成员函数的行为像个 const,并将发生"悬挂号码牌"(dangling handle)的可能性降至最低.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值