避免返回对象内部构件的句柄,这样也会提高封装性,帮助 const 成员函数产生 cosnt 效果。
#include <iostream> using namespace std; class Point { public: Point() { cout<<"Point()"<<endl; } Point(int x, int y) { cout<<"Point(int x, int y)"<<endl; this->x = x; this->y = y; } void setX(int newVal) { x = newVal; } void setY(int newVal) { y = newVal; } int &getX() { return x; } int getY() { return y; } ~Point() { cout<<"~Point()"<<endl; } private: int x; int y; }; struct RectData { Point ulhc; Point lrhc; }; class Rectangle { public: Rectangle(){} Rectangle(Point p1, Point p2):pData(0) { pData = new RectData; pData->ulhc = p1; pData->lrhc = p2; } //Point& upperLeft() const //如果没有&,返回的是pData->ulhc的拷贝,而非pData->ulhc本身;后续对pData->ulhc的拷贝赋值,并不会改变它的本体 Point& upperLeft() const { return pData->ulhc; } //const Point& upperLeft() const //返回const 类型,会使对象内部构建只读,提高封装性 Point& lowerRight() const { return pData->lrhc; } void Print() const { cout<<"upperLeft: "<<upperLeft().getX()<<" "<< upperLeft().getY()<<endl; cout<<"lowerRight: "<<lowerRight().getX()<<" "<< lowerRight().getY()<<endl; } ~Rectangle() { if( 0 != pData) { delete pData; pData = 0; } } //private: RectData *pData; }; const Rectangle boundingBox( ) { Point coord1(0, 0); Point coord2(100, 100); const Rectangle rec(coord1, coord2); return rec; } int main() { Point coord1(0, 0); Point coord2(100, 100); const Rectangle rec(coord1, coord2); rec.Print(); rec.upperLeft().setX(50); rec.upperLeft().setY(51); rec.Print(); //调用会返回一个新建的临时的 Rectangle 对象。这个对象没有名字,所以我们就称它为 temp。 //于是 upperLeft 就在 temp 上被调用,这个调用返回一个引向temp的一个内部构件的引用,特别是,它是由Points构成的。 //在这个语句的末尾,boundingBox 的返回值temp被销毁了,这将间接导致 temp 的 Points 的析构。 //接下来,剩下 pUpperLeft 指向一个已经不再存在的对象;pUpperLeft 空悬在创建它的语句的末尾! //这就是为什么任何返回一个对象的内部构件的句柄的函数都是危险的。 Point *pUpperLeft = &(boundingBox( ).upperLeft()); }