28. Avoid returning "handles" to object internals

避免返回handles指向对象内部成员

示例代码如下:

class Point
{
public:
	Point(int x, int y);
	...
	void SetX(int x);
	void SetY(int y);
	...
};

struct RectData
{
	Point ulhc;
	Point lrhc;
};

class Rectangle
{
public:
	Point& upperLeft() const { return pData->ulhc;}
	Point& lowerRight() const { return pData->lrhc;}
	...
private:
	std::shared_ptr<RectData> pData;	
}

调用如下:

Point coord1(1, 1);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().SetX(50); // 标识1

标识1处的代码编译没有问题,但是语义上却有矛盾。rec为一个常量,却可以通过标识1处修改其内部的值。

这带给我们两个教训

  • 成员变量的封装性最多只等于"返回其reference"的函数的访问级别。
  • 如果const成员传出一个reference,后者所指数据与对象自身有关联,而它又被存储于对象之外,那么这个函数的调用者可以修改那笔数据。

Reference、指针和迭代器统统都是所谓的handles(用来取得某个对象),而返回一个"代表对象内部数据"的handle,随之而来的便是"降低对象封装性"的风险。它也可能导致"虽然调用const成员函数却造成对象状态被改变"。

修改比较简单,返回引用时加上const。

class Rectangle
{
public:
	...
	const Point& upperLeft() const { return pData->ulhc; }
	const Point& lowerRight() const {return pData->lrhc; }
}

即便如此,upperLeft和lowerRight还是返回了"代表对象内部"的handles,有可能在其他场合带来问题。它可能导致dangling handles,这种handles所指东西(的所属对象)不复存在的对象。最常见的来源就是函数返回值。

示例如下:

class GUIObject { ... }
const Rectangle boundingBox(const GUIObject& obj);

使用如下:

GUIObject* pgo;
...
const Poin* pUpperLeft = &(boundingBox(*pgo).upperLeft()); // 标识2

标识2处执行完后,pUpperLeft即为一个悬挂指针,其指向的临时对象已经析构。

这就是为什么函数如果返回一个handle代表对象内部成分总是危险的原因。不论这所谓的handle是个指针或迭代器或reference,也不论这个handle是否为const,也无论那个返回handle的成员函数是否为const。这里唯一的关键是,有个handle被传出来了,一旦如此你就是暴露在"handle比其所指对象更长寿"的风险下。

这并不意味你绝对不可以让成员函数返回handle。有时候你必须那么做。例如operator[]就允许你"摘采"strings和vectors个别元素。而这些opreator[]s就是返回references指向"容器内的数据",那些数据会随着容器被销毁而销毁。尽管如此,这样的函数毕竟是例外,不是常态。

请记住:

避免返回handles(包括refercence、指针、迭代器)指向对象内部。遵守这个条款可增加封装性,帮助const成员函数的行为像个const,并将发生dangling handles的可能性降到最低。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值