Effective C++学习笔记——构造/析构/拷贝运算

条款9:决不再构造和析构过程中调用virtual函数,包括通过函数间接调用virtual函数。
应用:想在一个继承体系中,一个derived class被创建时,某个调用(例如生成相应的日志log)会有相对应的实现。
原因: base class的构造函数会先被调用,而在base class 构造期间virtual函数绝不会下降到dedrived class阶层。事实上,C++的其它部分(dynamic_cast & typeid),在此期间也是一样的把对象视为base class。
 
解决办法:籍由”令derived class 将必要的构造信息向上(通过函数参数)传递至base class的构造函数“。可以在dedrived class中定义一个private static函数来得到该构造信息, 定义为static是为了避免使用尚未初始化好的dedrived class 成员。
 
条款10、11: 令assignment操作符返回一个reference to *this。同时注意在operator=中处理”自我复制“!
说明:operator=要考虑”自我复制安全性“和”异常安全性“。涉及的技术包括:比较”来源对象“和”目标对象“的地址、精心周到的语句顺序、以及copy-and-swap技术。
   1: class A
   2: {
   3:     ...
   4: private:
   5:     int *p;            
   6: }
   7: //1 各种不安全
   8: A& A::operator=(const A& rhs)
   9: {
  10:     delete p;
  11:     p = new A(*rhs.p);
  12:     return *this;
  13: }
  14:  
  15: //2 语句顺序的改变,带来“自我复制安全”(虽然也许不够高效)与“异常安全”。
  16: A& A::operator=(const A& rhs)
  17: {
  18:     pOrig = p;
  19:     p = new A(*rhs.p);
  20:     delete pOrig;
  21:     return *this;
  22: }
  23:  
  24: //3 copy-and-swap技术
  25: void A::swap(A& rhs)
  26: {
  27:     ...//交换*this与rhs
  28: }
  29: A& A::operator=(const A& rhs)
  30: {
  31:     A temp(rhs);
  32:     swap(rhs);
  33:     return *this;
  34: }
  35:  
  36: //4 巧妙伶俐的利用值传递在制造临时副本,即使有可能更为高效(在“函数参数构造”)却牺牲了清晰性。
  37: A& A::operator=(const A rhs)
  38: {
  39:     swap(rhs);
  40:     return *this;
  41: }
 
条款12:复制对象时勿忘其每一个成分
备注:不要尝试以某个copying函数来实现另一个copying函数(copy构造函数,operator=函数)。
posted @ 2013-10-02 22:58  oldpeanut  阅读(220)  评论(0编辑  收藏  举报