C++ 将构造函数虚化,动态产生对象

上一篇 / 下一篇  2012-09-18 14:05:02 / 个人分类:C++

(J_H_$sP0Hw0  我们知道构造函数有一个必须遵守的规则,即构造函数不能定义为虚函数。但有一个具体的应用是要求是在不同的场景下通过一个指针或者引用生成不同的对象,这就类似于类型的动态生成,即在执行期才能确定具体的对象。这怎么实现呢?51Testing软件测试网w~p/Mfs&P%P

51Testing软件测试网K{]#r9Y9Qd-`j'De

  下面我们介绍两种方法:

ja-_T h }`x}0

d7HID%W3s0  1、不管是在effective c++ 还是在设计模式中,提到的一种特别的替代继承的方法,即组合。采用组合的方法来实现构造函数虚化的功能。具体实现方式为:

&kOL#~ Tfk0

-o-}3vdkC-W S0 51Testing软件测试网 n1t8r1[!J'~W'X

class base {
jB!P,?QNwm0//抽象基类,其中至少含有一个纯虚函数,但其构造函数非虚51Testing软件测试网 Z1}z ? Hc0Tf'G
      public:51Testing软件测试网^Oj:U l)]g(o Y)T
           ....
"D(vM;p&N0P4e,G4dE0};51Testing软件测试网"q$Z4j9} a(NEv
class derive1:public base {51Testing软件测试网+k)p0VF/o BC
      public:
cP3SsaT$k0           ....
.m4Nc9@l/lm@/BWV0};
x%DK8G'@t ]F"u&M0class derive1:public base {51Testing软件测试网V5[H6XLk2t
//没有内含任何纯虚函数
8P/zP#dl@/E5A]3mL^0      public:51Testing软件测试网db:Fk+G#Zq+i0H&Z
           ....
O&^8} e_/F'Dw0};
L`,a:g2V(zF0class derive2:public base {51Testing软件测试网;h/R2\!{J&}
//没有内含任何纯虚函数51Testing软件测试网0]!C(Uf5Q;WI
      public:
%lk!z!rW-G/Q[ P4t$l$@jI0           ....
D;xmEv,D0};51Testing软件测试网8TtZx$a3T!d
class  object {
K\qR4{-`0      public:
zn!\#a Q1l x,e?F0         ...51Testing软件测试网kiSuO ?z%t
       private:
F(m5_cpPU(G6Ny0           list<base*> components;51Testing软件测试网b q0[]C4` [$h@
};
51Testing软件测试网1} L#JS q7G2v(|

  在上面的代码中,class object含有一个list对象用来装载base类对象,但是由于base类是一个抽象类,所以list中得内容实际为derive1或者为derive2对象,实现了动态产生对象。51Testing软件测试网%J2O%LXu S^

'TNxClT&pdn*~0  在object类的实现函数还有注意下面的代码:

D~ lP@ Mv UB;C0

5EZ6~w"f L7M0 51Testing软件测试网!U1Q2p*m'L%Z

object:object(base* b) {51Testing软件测试网S@(jmYu.L$l:Z
      if(b) {
5r,h] u8X@0          components.push_back(b);//将具体的base的子类对象加到components list尾端     51Testing软件测试网4wRqI{e m tk?
     }51Testing软件测试网3L zm rw4[G
}

p;F%JV R/J0  2、还有一种方法是利用“虚函数的返回类型”规则中得一个宽松点,那是c++标准比较晚才被接纳的一个规则。当derived class重新定义其base class的一个虚函数时,不再需要一定得声明与原本相同的返回类型。如果函数的分返回类型是个指针或者引用,并指向一个base class,那么derived class的函数可以返回一个指针或引用指向该base class的derived class。这不会造成c++的类型错误,却准确的声明出像virtual copy constructors这样的函数。51Testing软件测试网,M1g[v v9oe;k

6a.ezC6\2{0 51Testing软件测试网&mq*ty"T]6k/Kp

class base {51Testing软件测试网 y1Vx@!M3e%sXR1e
      public:51Testing软件测试网Xh&Zf2MZ#HTm
//声明virtual copy constructor
8?-r$zi(Pu Ya#]"X0           virtual base *clone() const=0;
C#fN~.s/E4U0            ....
0}c9f S*n)g0};51Testing软件测试网ZZV9ubN"\9| n3V
class derive1:public base {51Testing软件测试网&i$HV^A*k,fFs
//声明virtual copy constructor51Testing软件测试网G'H6}g!]
           virtual derive1 *clone() const51Testing软件测试网-ZuC3F T0LC
           {51Testing软件测试网A8ra VtB l
                    return new derive1(*this);51Testing软件测试网_p"BLw8_D,{1s
            }51Testing软件测试网/X] Z_0u5k
            ....51Testing软件测试网0PgxI0u5bi4Q R
};51Testing软件测试网3X*T%~!vO"tS
class derive2:public base {51Testing软件测试网\f5a|8Cw-T9I^ A
//声明virtual copy constructor
p|UlDt0           virtual derive2 *clone() const
m ~6XaP,K)V6?S0           {
-K(D2hv9] I K3e i0                    return new derive2(*this);51Testing软件测试网?A Y*Kc
            }
_NA1ZO8{[0            ....
0YN2\(j&k?0};
Ih@]@0class  object {
&O.X[T Un0      public:
pX;C2r j0          object(const base& rhs);51Testing软件测试网)v3R{ Y)ih
         ...
Y4Rs T4A V0       private:
I(V.Q-`z`c Z%@0           list<base*> components;
l1M(yP~6E0};

W*O0~-A1lf]0  object类的实现方法有:51Testing软件测试网:|MHB q7}

gD+H6Daq,k0 51Testing软件测试网 o3fBP!h,@8t

object:object(const base& rhs) {51Testing软件测试网@3c M,rVp3x H^
      for(list<base*>::const_iterator it=rhs.components.begin();it!=rhs.components.end();it++) {51Testing软件测试网-dFPw;?J
          components.push_back((*it)->clone());//将具体的base的子类对象加到components list尾端    
3v#Q$N6q O8uU.Q6WW,r0     }51Testing软件测试网g-lO,k1A)|(u0ju\)M{
}
51Testing软件测试网|L)B0m s m

  注意,上面的两种方法并不是真正的将构造函数直接定义为虚函数,而是采用其他的方法将构造函数产生虚化的效果。

*C+Q:q:vG7z1j.Rn0

TAG:

 

评分:0

我来说两句

Open Toolbar