(一)

有时候为了让一个对象尽量小,能够把数据放在另外一个辅助的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,并将“虚号码牌“的可能性减少到最低。

最新文章

  1. 【Win10 应用开发】语音命令与App Service集成
  2. TSQL order by 子句中排序列的多种写法
  3. HDU 2045 不容易系列之(3)—— LELE的RPG难题 (递推)
  4. Struts1中ActionForward的技巧介绍
  5. 关于Encoding.GetEncoding(&quot;utf-8&quot;)和Encoding.GetEncoding(&quot;GB2312&quot;)及Encoding.Default
  6. thinkphp autoload 命名空间自定义 namespace
  7. C语言程序设计做题笔记之C语言基础知识(下)
  8. Codeforces 22B Bargaining Table
  9. Windows 8.1下 MySQL绿色版安装配置与使用
  10. 挺好用的SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面)
  11. SPOJ DIVCNT2 [我也不知道是什么分类了反正是数论]
  12. R+tmcn笔记︱tmcn包的基本内容以及李舰老师R语言大会展示内容摘录
  13. Python二次编码、小数据池之心照神交
  14. PyCharm下使用Scrapy建立爬虫项目--MyFirstSpiderObject
  15. HDU 4027 Can you answer these queries【线段树】
  16. redis介绍以及安装
  17. 腾讯Ocr文字识别
  18. 【读书笔记】Android平台的漏洞挖掘和分析
  19. IECapt、CutyCapt 生成网页快照
  20. 【Oracle】Update方法

热门文章

  1. Net Core-Razor
  2. [LeetCode] Print All Combinations of a Number as a Sum of Candidate Numbers
  3. faith的23堂课:培养良好的工作方法与做事风格
  4. SQL server语句练习
  5. 我在知乎上关于Laser200/310电脑的文章。
  6. android.graphics.Color
  7. Linux下同时运行不同版本的qt程序
  8. 关于IOCP,某些地方就是不让人彻底舒服(WSASend重叠post数据)
  9. 普联的路由器TL-WR842N和TL-WR845N还有 TL-WR847N哪一个更好,我是家用
  10. 广东省-IT公司红黑榜排名