Effective C++之条款19、20

条款19:设计class犹如设计type

    如何设计搞笑的classes呢?几乎每一个class都要求你面对以下提问:

  • 新type的对象应该如何被创建和销毁? 这会影响到你的class的构造函数和析构函数以及内存分配函数和释放函数的设计。
  • 对象的初始化和对象的赋值该有什么的差别? 这个答案决定你的构造函数和赋值操作符的行为,以及期间的差异。很重的是别混淆了初始化和赋值,因为它们对应于不同的函数调用(见条款4)。
  • 新type的对象如果被passed by value,意味着什么? 记住,copy函数用来定义一个type的pass-by-value该如何实现。
  • 什么是新type的“合法值”? 对于class的成员变量而言,通常只有某些数值集是有效的。这决定了你的class必须维护的约束条件。
  • 你的新type需要配合某个继承图系吗? 如果你继承自某些既有的classes,你就受到那些classes的设计的束缚,特别是受到“它们的函数是virtual或non-virtual”的影响(见条款34和36)。
  • 你的新type需要什么样的转换? 你的type生存于其他众多types之间,因而彼此之间该有转换行为吗?如果有需要,就必须在相应的类内写一个类型转换函数(隐式的或显示的等)。
  • 什么样的操作符和函数对此新type而言是合理的? 这个问题的答案决定你将为你的class声明哪些函数。
  • 什么样的标准函数应该驳回? 那些正是你必须声明为private(见条款6)。
  • 谁该取用新type的成员? 这个问题答案决定那个成员是public,哪个是protected,哪个是private。也决定哪个class或function应该是friends。
  • 什么是新type的未声明接口? 他对效率、异常安全性(见条款29)以及资源运用(例如多任务锁定和动态内存)提供何种保障?
  • 你的新type有多么一般化? 或许你其实并非定义一个新的type,而是定义一整个types家族。此时你应该定义一个新的class template。
  • 你真的需要一个新的type吗? 如果只是定义新的derived class以便为既有的class添加机能,那么说不定单纯定义一个或多个non-member函数或templates,更能达到目标。


条款20:宁以pass-by-reference-to-const替换pass-by-value

    C++默认以by value方式传递对象至函数,而调用端所获得的也是函数返回值的一个副本。这些副本都是由对象的copy构造函数产出,这可能使得pass-by-value成为费时的操作。当以by reference方式传递时,则不会有任何构造函数和析构函数被调用。当然以by reference传递参数时,需对其加上const修饰,以保证其不会被修改。

    以by reference方式传递参数也可以避免slicing(对象切割)问题。当一个dervied class对象以by value方式传递并被视为一个base class对象,base class的copy构造函数会被调用,而“造成此对象的行为像个derived class对象”的那些特化性质全被切割掉了,仅仅留下一个base class对象。假设你在一组classes上工作,用来实现一个图形窗口系统:

class Window {
public:
	...
	string name() const      //返回窗口名
	virtual void display() const;   //显示窗口和其内容
};
class WindowWithScrollBars: public Window {
public:
	...
	virtual void display() const;
};
void printNameAndDisplay(Window w)             //参数可能被切割
{
	cout<<w.name();
	w.display();
}
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);

    参数w会被构造成为一个Window对象;它是passed by value。解决·切个问题的办法,就是以by reference-to-const的方式传递w:

void printNameAndDisplay(const Window& w)   //参数不会被切割
{
	...
}

请记住

  • 尽量以pass-by-value-to-const替换pass-by-value。前者通常比较高效,并可避免切割问题。
  • 以上规则并适用于内置类型,以及STL的迭代器和函数对象。对他们而言,往往以pass-by-value方式更为合适。
发布了33 篇原创文章 · 获赞 6 · 访问量 571

猜你喜欢

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