More Effective C++ (虚拟构造函数)
在了解代码之前,请先仔细阅读这些概念:
<1>虚构造函数:
一种允许你做一些 C++不直接支持的事情的用法。
你可能通过虚函数 virtual clone()(对于默认拷贝构造函数)或虚函数 virtual create()(对于默认构造函数),得到虚构造函数产生的效果。
<2>虚拟拷贝构造函数:
一种特殊的虚拟构造函数――虚拟拷贝构造函数――也有着广泛的用途。
虚拟拷贝构造函数能返回一个指针,指向调用该函数的对象的新拷贝。
因为这种行为特性,虚拟拷贝构造函数的名字一般都是copySelf,cloneSelf或者是像下面这样就叫做clone。
<3>协变返回类型:
注意:下述代码的实现利用了被采纳的较宽松的虚拟函数返回值类型规则。
被派生类重定义的虚拟函数不用必须与基类的虚拟函数具有一样的返回类型。
如果函数的返回类型是一个指向基类的指针(或一个引用),那么派生类的函数可以返回一个派生类的指针(或引用)。
这不是C++的类型检查上的漏洞,它使得有可能声明像虚拟构造函数这样的函数。
这就是为什么Circle 的clone函数能够返回Circle * 和 Square 的clone也能够返回Square *的原因,即使Shape 的clone返回值类型却为Shape *。
备注:根据坊间记录,以前的编译器是不支持这个东东的。
<4>虚拟构造函数
因为它能建立新对象,它的行为与构造函数相似,而且因为它能建立不同类型的对象,我们称它为虚拟构造函数。
虚拟构造函数是指能够根据输入给它的数据的不同而建立不同类型的对象。
虚拟构造函数在很多场合下都有用处,从磁盘(或者通过网络连接,或者从磁带机上)读取对象信息只是其中的一个应用。
示例代码1如下:
1 #include<iostream> 2 using namespace std; 3 class Shape 4 { 5 public: 6 virtual ~Shape() { } // 虚析构函数 7 8 // 使用默认拷贝构造函数 ,more effective c++中成为虚拟拷贝构造函数 。涉及"协变返回类型" 9 virtual Shape* clone() const = 0; 10 // 使用默认构造函数 11 virtual Shape* create() const = 0; 12 }; 13 14 class Circle : public Shape 15 { 16 public: 17 Circle() 18 { 19 cout<<"Construction Circle "<<this<<endl; 20 } 21 public: 22 //在 clone() 成员函数中,代码 new Circle(*this) 调用 Circle 的默认拷贝构造函数来复制this的状态到新创建的Circle对象 23 Circle* clone() const 24 { 25 return new Circle(*this); 26 } 27 //在 create()成员函数中,代码 new Circle() 调用Circle的默认构造函数。 28 Circle* create() const 29 { 30 return new Circle(); 31 } 32 //析构函数 33 ~Circle() 34 { 35 cout<<"Destroy Circle "<<this<<endl; 36 } 37 38 }; 39 40 class Square : public Shape 41 { 42 public: 43 Square() 44 { 45 cout<<"Construction Square "<<this<<endl; 46 } 47 public: 48 //在clone()成员函数中,代码 new Square(*this) 调用Square的默认拷贝构造函数来复制this的状态到新创建的Square对象 49 Square* clone() const 50 { 51 return new Square(*this); 52 } 53 //在 create()成员函数中,代码 new Square() 调用Square的默认构造函数。 54 Square* create() const 55 { 56 return new Square(); 57 } 58 //析构函数 59 ~Square() 60 { 61 cout<<"Destroy Square "<<this<<endl; 62 } 63 64 }; 65 //虚构造函数 66 void userCode(Shape &s) 67 { 68 Shape* s2 = s.create(); 69 Shape* s3 = s.clone(); 70 71 delete s2; // 在此处,需要虚析构函数 72 delete s3; 73 } 74 75 int main() 76 { 77 Circle c; 78 userCode(c); 79 80 Square s; 81 userCode(s); 82 } 83 84 /* 85 *运行结果与分析: 86 Construction Circle 003EF8D8 调用Circle构造函数创建对象c 87 Construction Circle 00234B98 userCode函数中s.create()函数调用Circle构造函数创建新对象 88 Destroy Circle 00234B98 析构新构造对象 89 Destroy Circle 00234BD8 析构克隆对象 90 Construction Square 003EF8CC 调用Square构造函数创建对象s 91 Construction Square 00234B98 userCode函数中s.create()函数调用Square构造函数创建新对象 92 Destroy Square 00234B98 析构新构造对象 93 Destroy Square 00234BD8 析构克隆对象 94 Destroy Square 003EF8CC 析构对象s 95 Destroy Circle 003EF8D8 析构对象c 96 */
示例代码2如下:
1 #include<iostream> 2 using namespace std; 3 4 class Object 5 { 6 public: 7 Object() 8 {} 9 virtual ~Object() 10 {} 11 virtual void print() const = 0; 12 public: 13 virtual Object* CloneSelf() const = 0; 14 virtual Object* CopySelf() const = 0; 15 }; 16 17 class Int:public Object 18 { 19 private: 20 int value; 21 public: 22 Int(int x = 0):value(x) 23 {} 24 ~Int() 25 {} 26 void print() const 27 { 28 cout<<value<<endl; 29 } 30 public: 31 Int* CloneSelf() const 32 { 33 return new Int(); 34 } 35 Int* CopySelf() const 36 { 37 return new Int(*this); 38 } 39 }; 40 class Char:public Object 41 { 42 private: 43 char value; 44 public: 45 Char(char x='h'):value(x) 46 {} 47 ~Char() 48 {} 49 void print() const 50 { 51 cout<<value<<endl; 52 } 53 public: 54 Char* CloneSelf() const 55 { 56 return new Char(); 57 } 58 Char* CopySelf() const 59 { 60 return new Char(*this); 61 } 62 }; 63 class Double:public Object 64 { 65 private: 66 double value; 67 public: 68 Double(double x=12.34):value(x) 69 {} 70 ~Double() 71 {} 72 void print() const 73 { 74 cout<<value<<endl; 75 } 76 public: 77 Double* CloneSelf() const 78 { 79 return new Double(); 80 } 81 Double* CopySelf() const 82 { 83 return new Double(*this); 84 } 85 }; 86 87 class SeqList 88 { 89 Object *data[10]; 90 int MaxSize; 91 int len; 92 public: 93 //虚拟构造函数 94 Object * CloneObj(Object &ob) 95 { 96 return ob.CloneSelf(); 97 } 98 //虚拟拷贝构造 99 Object * CopyObj(Object &ob) 100 { 101 return ob.CopySelf(); 102 } 103 public: 104 SeqList() 105 { 106 MaxSize = 10; 107 for(int i = 0; i < MaxSize; ++i) 108 { 109 data[i]=NULL; 110 } 111 len = 0; 112 } 113 114 ~SeqList() 115 {} 116 void pushClone(Object &ob) 117 { 118 data[len++] = CloneObj(ob); 119 } 120 void pushCopy(Object &ob) 121 { 122 data[len++] = CopyObj(ob); 123 } 124 void print() const 125 { 126 for(int i = 0; i < len; ++i) 127 { 128 data[i]->print(); 129 } 130 cout<<endl; 131 } 132 }; 133 void main() 134 { 135 SeqList mylist; 136 Int intObj; 137 Char charObj; 138 Double douObj; 139 mylist.pushClone(intObj); 140 mylist.pushClone(charObj); 141 mylist.pushClone(douObj); 142 mylist.pushCopy(intObj); 143 mylist.pushCopy(charObj); 144 mylist.pushCopy(douObj); 145 mylist.print(); 146 } 147 /* 148 0 149 h 150 12.34 151 0 152 h 153 12.34 154 */
Good Good Study, Day Day Up.
顺序 选择 循环 坚持