• 【转】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.

  • 相关阅读:
    百度地图API开发----手机地图做导航功能
    手机端列表做异步加载!
    onethink判断是否是手机访问?
    PHP中文字数限制:中文字符串截取(mb_substr)
    onethink封装arclist调用文章列表!
    问答项目---提问回答采纳处理!
    问答项目---面包削导航的处理!
    问答项目---处理待解决/已回答/高悬赏/零回答!
    问答项目---格式化输出提问时间!
    问答项目---提问按钮如何做!
  • 原文地址:https://www.cnblogs.com/zhiqli/p/3408777.html
Copyright © 2020-2023  润新知