论虚构造函数与虚复制构造函数的实现!

 一看标题,这个有点过,甚至有点哗众取宠性质,因为从C++的语言角度,其实构造函数及复制构造函数是并不存在虚函数形式的,原因是为何,先把C++ Primer中的原话引述上来:……只有析构函数应定义为虚函数,构造函数不能定义为虚函数。构造函数是在对象完全构造之前运行的,在构造函数运行的时候,对象的动态类型还不完整。

        甚至有人一看见这文章标题,就要骂我,构造函数本来不允许虚,而且这么久还没见过虚构造函数,而且就如上边提到Lippman的权威著作也写明。更甚至者,网上有人对于虚复制构造函数这一词的反应:“我学了 10 年 C++,还没听说过有“虚复制构造函数”。”笔者看了立刻第一反应:一个不愿意看书又自大兼口没遮拦、误导新手的糊涂虫!

        有某些情况是需要用到虚复制构造函数等等,例如,想象一下,如果有一项功能,程序为一个基类+N个派生类,而基类充当的是一个抽象接口类的角色,而到各派生类才会依据数据来建立各自的对象,这个时候虚拟构造函数或虚复制构造函数就有用处了,就如More Effective C++  条款M25的例子,一个新闻类(一个接口基类),有图片(派生类)、文字等不同东西(不同的派生类),平时不用时存储在磁盘上,不同的东西当然放的地方有不同了,构造函数就是利用istream读取,所以,当要对不同类型的新闻内容操作时,就会建立不同的对象,这样就需要根据不同内容建立不同对象,这时,虚复制构造函数就产生用处了(当然,某部分人要违反面向对象封装这种设计哲学,又不顾效率的话,有接口不用,特意直接分别用派生类来构建对象的这个情况,那么我想说:“C++真的不适合你。”)。

        C++不允许直接对构造函数声明为虚啊,包括复制构造函数,那么如何实现呢?其实是有方法的,笔者在两本书中也看见过虚复制构造函数的实现方法,其一是C++大师Scott Meyers写的More Effective C++ 的条款 M25,就正正是讨论这个问题!而另外一本则是一本一个美国花旗银行前开发部副总写的C++初学者教程,名字是《21天学通C++》(在GOOGLE上输入虚复制构造函数就会有人说在看这个书,看到这部分不明何解,之后还有SB回复上边第二段的蓝色字部分。如果一个没编程基本的人,要说21天能完全掌握C++就有点扯,但老实说,那本书的教学内容广度和深度及对学习者编程习惯的强调要比国内相当多的C++教程好得多),扯远了,下边说回来,既然C++语法中没有直接方法实现,但又有需要用到的场合,那么如何实现呢?其实好简单,通过一个虚函数方法建议一个新的对象,如下边代码所示:

……

1、class A
2、{
3、public:
4、A(int);
5、 A(A const &rhs);

6、 ~A();

7、 /* 如果基类只是一个接口类,此行还可以直接改为virtual  A* clone() =0;具体行8、为于具体类中再定义 */

8、virtual  A* clone() {  return  new A (*this)  }   
9、private: ……
10、};

11、class B:public A
12、{
13、public:
14、 B(int);
15、 B(B const &rhs);

16、 virtual B* clone(){  return  new  B(*this)  } 

17、private:
18、……
19、};

        上边代码第8和第16行就是一个虚复制构造函数机制,关键就是那个clone方法中的功能语句:return  new  B (*this),这句的意思是:建立一个某个类的对象(此例中就是B类),并且,在新建这个对象时,将*this作参数传给复制构造函数,因为每定义一个对象对,C++就会依据类型调用相应的构造函数或者复制构造函数,而 new  B (*this)这种形式,正好就是复制构造B(B const &rhs);的形式,如果看不明白,可以看下边例子:其实return  new  B (*this)这个语句,就类似于:X *p=new X;   X*q=new X(*p);当然,作用不一样,但原理相似,例如:

图片

红线的一句在新建对象时就会调用复制构造函数了!

        而虚复制构造函数则是利用虚函数的性质(能覆盖基类的特质),执行一个创建某个类的对象的方法,由于创建某个类的对象时,会执行某一个类的构造函数或复制构造函数,如果该类是一个接口类的派生类,则和虚函数实现达到目的了,而就算是一般类的派生类,也会在执行基类的复制构造后自动执行派生类的复制构造,这样同样达到目的。

        虚构造函数可以如上边提到的虚复制构造函数一样处理,其实本文提到的虚复制构造函数,我个人觉得可以说成是“利用虚函数及新建对象的机制实现构造函数及虚构造函数的多态性。”只不过,因为其能够实现虚复制构造函数这一种性质,所以人们就将其说成虚复制构造函数、虚构造函数。

        说了一晚的虚复制构造函数,下边就说说虚构造函数了,其实差别不大,只要将virtual B* clone(){  return  new  B(*this)  }这句改成构造函数的形式,在本例中就是virtual B* clone(){  return  new  B()  }。

        有了虚构造函数嘛,如何用呢,当然是用指针来调用了,函数的类型也是一个返回值为指针的类型嘛,而且对虚函数起作用的通常也是指针。

        具体调用格式嘛:TYPE *指针名=new 派生类;    指针->clone();(TYPE要是基类的,否则搞这么多东西后做些违反设计哲学的东西无意义)。

        值得注意的地方:

        由于这样的过程替代了 X *x=new X;这个过程,所以在使用后注意记得释放指针,万分注意,当然,这个可以在析构中实现,当然,析构可以直接是虚的,所以没什么难度。

         文章就到此,本文只为记录一下个人所了解的情况,至于某些说自己学了多少年C++,没听过虚构造函数的人如果强行要辩论说虚构造、虚复制构造没可能、没用的话,先去看清楚More Effective C++的M25条款,还有意见就去找顶级C++大师Scott Meyers反映,本人得知该方法某程度上也是从那位大量的杰作中得知的,到目前为止亦相信该实现方法的正确性,要是你能辩倒Scott Meyers的话,可能下一版More Effective C++的感谢名单中会有你的大名。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值