Effective C++之条款27、28

条款27:尽量少做转型动作

    C++规定的设计目标之一是,保证“类型错误”绝不可能发生。这是一个极具价值的保证。C++提供四种新式转型(常常被称为new-style或C+±style casts):

const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)
  • cosnt_cast通常被用来将对象的常量性转除。他也是唯一由此能力的C+±style转型操作符。
  • dynamic_cast主要用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。它是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
  • reinterpret_cast意图执行低级转型,实际动作可能取决于编译器,这也就表示他不可移植。
  • static_cast用来强迫隐式转换,例如将non-const对象转换为const对象,或将int转为double等等。它也可以执行上多种转换的反向过程,例如将void*指针转为non-const----这个只有const_cast才能办到。

    当调用一个explicit构造函数将一个对象传递给一个函数时,会使用旧时转型。例如:

class Widget {
public:
	explicit Widget(int size);
	...
};
void doSomeWork(const Widget& w);
doSomeWork(Widget(15));                 //以一个int加上“函数风格”的
										//转型动作创建一个Widget
doSomeWork(static_cast<Widget>(15));    //以一个int加上“C++风格”的
										//转型动作创建一个Widget。

请记住

  • 如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。
  • 如果转型是必要的,试着将它隐藏于某个函数背后。
  • 宁可使用C++ -style转型,不要使用旧式转型。前者很容易辨识出来,而且也比较有着分门别类的职掌。

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

    假设你的程序涉及矩形,为了让一个Rectangle对象尽可能小,你可能会决定不把定义矩形的这些点放在Rectangle对象内,而是放在一个辅助的struct内再让Rectangle去指它:

class Point {};
struct RectData {
	Point ulhc;
	Point lrhc;
};
class Rectangle {
public:
	...
	Point& upperLeft() const { return pData->ulhc; } //返回底层的Point对象
	Point& lowerRight() const { return pData->lrhc; }
	...
private:
	shared_ptr<RectData> pData;
};

     Point是个用户自定义类型,所以根据条款20给我们的忠告,这些函数应该返回reference,指向底层的Point对象。这样设计可通过编译,但却是错的。实际上它是自我矛盾的。一方面upperLeft和lowerRight被声明为const成员函数,目的是为了让客户查看相关坐标点,而不是去修改他。另一方面两个函数却都返回了reference指向private内部数据,调用者于是可通过这些reference更改内部数据!

    我们可以通过对返回类型添加const修饰即可:

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

请记住

  • 避免返回handles(包括reference、指针、迭代器)指向对象内部。遵守这个条件可增加封装性,帮助const成员函数的行为像个const,并将发生“dangling handles(悬挂)”的可能性降至最低。
发布了33 篇原创文章 · 获赞 6 · 访问量 567

猜你喜欢

转载自blog.csdn.net/weixin_43519984/article/details/102649528