Effective C++:条款28:避免返回 handles 指向对象内部成员

Effective C++:条款28:避免返回 handles 指向对象内部成员

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

全栈程序员社区此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“全栈程序员社区”或者“www_javaforall_cn”或者微信扫描右侧二维码都可以关注本站微信公众号。

(一)

有时候为了让一个对象尽量小,能够把数据放在另外一个辅助的struct中,然后再让一个类去指向它。看以下的代码:

class Point {
public:
	Point(int x, int y);
	void setX(int newVal);
	void setY(int newVal);
};

struct RectData {
	Point ulhc;
	Point lrhc;
};

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

这种设计看上去非常beautiful。可是却是错误的,实际上它是自相矛盾的,看以下的代码:

Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2);
rec.upperleft().setX(50);

错误的理由:(1)upperLeft()跟lowerRight()这两个函数都是const的,所以客户不能改动Rectangle;

(2)两个函数都返回reference指向private内部数据,调用者于是可通过这些reference更改内部数据。

upperLeft的调用者可以使用被返回的引用来更改成员。但rec事实上应该是不可变的(const)!

所以上面那种类的设计是错误的!!!

所以从这个样例中,我们能够得到下面的教训:

(1)成员变量的封装性会被引用破坏。

(2)假设const成员函数传出一个reference,后者所指的数据与对象自身有关联,而它又被存储于对象之外,那么这个函数的调用者能够改动那笔数据。

相同的道理,返回对象的引用、指针、迭代器都会造成这样的局面,它们都是“句柄”。返回一个代表对象内部数据的句柄,会减少对象的封装。

(二)解决的方法:

仅仅要对这两个函数的返回类型加上const就可以:

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

有了这种改变,客户就仅仅能读取矩形的Points,可是不能涂写它们。

(三)

上面那种解决方法尽管确保了内部对象不会被改动。可是却可能导致dangling handles(空悬的号码牌):这样的handles所指东西(的所属对象)不复存在。

这样的“不复存在的对象”最常见的来源就是函数返回值。

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

GUIObject* pgo;
const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft());

你会发现(boundingBox(*pgo).upperLeft())这是一个point对象。可是当这一句运行完后,这个暂时对象temp会被析构。这时,pUpperLeft会指向一个空的对象。也就出现了悬空现象。

因此,这就是为什么函数假设“返回一个handle代表对象内部成分“总是危急的原因。

请记住:

(1)避免返回handles指向对象的内部。遵守这个条款可添加封装性,帮助const成员函数更加像一个const,并将“虚号码牌“的可能性减少到最低。




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117932.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java的所有版本

    java的所有版本java16与JDK15一样,JDK16将是一个短期版本,支持六个月。将于2021年9月发布的JDK17将是一个长期支持(LTS)版本,将获得数年的支持。当前的LTS版本JDK11已于2018年9月发布。JDK16预计20213月到来。java16JavaSE15JavaSE14JavaSE13JavaSE12JavaSE11JavaSE10JavaSE9JavaSE8(8u211andlater)JavaSE8(8u

    2022年7月7日
    16
  • Idea激活码最新教程2022.1.2版本,永久有效激活码,亲测可用,记得收藏

    Idea激活码最新教程2022.1.2版本,永久有效激活码,亲测可用,记得收藏Idea 激活码教程永久有效 2022 1 2 激活码教程 Windows 版永久激活 持续更新 Idea 激活码 2022 1 2 成功激活

    2025年5月25日
    4
  • 八皇后问题详解(四种解法)

    八皇后问题详解(四种解法)如果你去百度百科八皇后这个问题,你会发现人家也是历史上有头有脸的一个问题,最后一句“计算机发明后就有一万种方式解决这个问题”读起来也让程序猿们很快活。闲话少说,开始阐述我的思路:最无脑的解法一定是八个for遍历,浪费了太多的计算资源在各种无用功上面,我们稍微构思一下:首先如何决定下一个皇后能不能放这里可以有两种思路,第一种是尝试维护一个8*8的二维矩阵,每次找到一个空位放下一个皇后就把对应行列对

    2022年6月30日
    22
  • 爱美眉aimeimei.pw整站下载、2G图片、上万数据

    爱美眉aimeimei.pw整站下载、2G图片、上万数据官网:http://www.aimeimei.pw美眉aimeimei.pw整站源码安装方法:1.把文件上传到你的站点的根目录,然后运行http://你的域名/install/index.php安装,根据提示填写好相关信息,点“下一步”…即可完成安装。注:若提示无法安装,页面出现DIY字样。请进入install文件夹,将install_lock.txt文件删掉。把index

    2025年11月15日
    4
  • xml语言

    xml语言

    2022年1月11日
    36
  • 白话空间统计之:Moran’s I(莫兰指数)

    白话空间统计之:Moran’s I(莫兰指数)Moran’sI这个东西,官方叫做:莫兰指数,是澳大利亚统计学家帕特里克·阿尔弗雷德·皮尔斯·莫兰(PatrickAlfredPierceMoran),在1950年提出的。一般是用来度量空间相关性的一个重要指标。

    2022年6月25日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号