C++基类,派生类,同名覆盖原则

  1. / 同名覆盖原则.cpp: 主项目文件。  
  2. #include "stdafx.h"  
  3. #include<iostream>  
  4. #include<string>  
  5. using namespace std;  
  6. class One  
  7. {  
  8. private:  
  9.     string name;  
  10.     int age;  
  11. public:  
  12.     virtual ~One( )=0{ }  
  13.     void Get_name( )const  
  14.     {  
  15.         cout<<"Name : "<<name<<endl;  
  16.     }  
  17.     void Get_age( )const  
  18.     {  
  19.         cout<<"Age : "<<age<<endl;  
  20.     }  
  21. protected:  
  22.     One( ) : name( "plato" ), age( 24 ){ }  
  23.     One( string N, int Age ) : name( N ), age( Age ){ }   
  24. };  
  25. class Two : public One  
  26. {  
  27. private:  
  28.     string sex;  
  29. public:  
  30.     Two( ) :One( ), sex( "female"){ }  
  31.     Two( string Name, int Age, string Sex ) : One( Name, Age ), sex( "Sex" ){ }  
  32.     ~Two( ){ }  
  33.     void Get_name( )const;  
  34.     void Get_age( )const;  
  35.     void Get_sex( )const;  
  36. };  
  37. void Two:: Get_name( )const  
  38. {  
  39.     One::Get_name( );  
  40. }  
  41. void Two::Get_age( )const  
  42. {  
  43.     One::Get_age( );  
  44. }  
  45. void Two::Get_sex( )const  
  46. {  
  47.     cout<<"Sex : "<<sex;  
  48. }  
  49. int main(array<System::String ^> ^args)  
  50. {  
  51.     Two juck;  
  52.     juck.Get_age( );  //default will call drived class method  
  53.     juck.One::Get_age( );  //Explicit  declare use base class method   
  54.     system("pause");  
  55.     return 0;  
  56. }  
 

 

#运行结果:运行结果

 

##现在来看通过多重继承中,出现同名类成员时的访问机制

 

[cpp]  view plain copy
  1. // 虚基类及其派生类构造函数.cpp: 主项目文件。  
  2.   
  3. #include "stdafx.h"  
  4. #include<iostream>  
  5. using namespace std;  
  6. class A  
  7. {  
  8. private:  
  9.     int a_value ;  
  10. public:  
  11.     A( int a ):a_value(a){ cout<<"Member of class A"<<endl ;}  
  12.     void fun( )const { cout<<"function of A"<<endl; }  
  13. };  
  14. class B : virtual public A  
  15. {  
  16. private:  
  17.     int b_value;  
  18. public:  
  19.     B( int a ,int b  ) : A(a),b_value(b){ cout<<"Member of class B "<<endl ;}  
  20. };  
  21. class C : virtual public A  
  22. {  
  23. private:  
  24.     int c_value ;  
  25. public:  
  26.     C( int a , int c ) : A(a),c_value(c){ cout<<"Member of class C "<<endl;}  
  27. };  
  28. class D :public B, public C  
  29. {  
  30. private:  
  31.     int d_value;  
  32. public:  
  33.     D( int a , int b , int c ,int d ) : A(a),B(a,b),C( a,c ),d_value( d ){ cout<<"Member of class D "<<endl ; }  
  34.     void fun( )_dconst { cout<<"function of D "<<endl; }  
  35.   
  36. };  
  37.   
  38. int main(array<System::String ^> ^args)  
  39. {  
  40.     D tmp( 10, 20, 30, 40 );  
  41.     tmp.fun_d( );    
  42.       
  43.     tmp.fun( );    
  44.     tmp.B::fun( );    
  45.     tmp.C::fun( );  
  46.   
  47.     system("pause");  
  48.     return 0;  
  49. }  

 

##下面一一分析:

 

int main(array<System::String ^> ^args)
{
 D tmp( 10, 20, 30, 40 );
 tmp.fun_d( );  
 
 tmp.fun( );  
 tmp.B::fun( );  
 tmp.C::fun( );

 system("pause");
    return 0;
}

首先来看tmp.fun_d( );tmp是一个第三继承类对象,它讲调用哪个成员函数呢?首先它会从当前域,及它所属的类区域查找,若查找不到对应的成员函数,它会向前查找。此处tmp所属的类D中已然已经定义了对应的成员函数fun_d( ),所以这里会直接调用 tmp.D::fun_d( );

 

再来看tmp.fun( ).类似上面,它首先从当前域即类D中查找fun()函数,若查找不到,会向前查找,直到找到。基类A中定义了fun(),所以这里会调用属于基类A的成员函数。

 

再来看tmp.B::fun( ).. 很显然,第三继承类D,第二继承类B 中都没有显式定义函数fun( ),这里的调用,意欲何为?由于类B由基类A公有派生而来,所以累B会继承类A 的成员,类似于基类A会在继承类B上映射相应的成员到相应的区域。(通过公有继承, 基类A会把public/protected 成员投射到继承类B相应的public/protected区域上,注意,是一对一投射。)。所以tmp.B::fun( )暗藏着继承机制的原理,及它所调用的实际上是类A的对应成员。

 

当然tmp.C::fun( )这个的访问机制同上。。

 

问题:当类C是通过私有继承机制,来继承类A时,这种访问会是什么样?

 

#运行结果:

运行结果

 

##下面稍微修改下:

 

[cpp]  view plain copy
  1. class D :public B, public C  
  2. {  
  3. private:  
  4.     int d_value;  
  5. public:  
  6.     D( int a , int b , int c ,int d ) : A(a),B(a,b),C( a,c ),d_value( d ){ cout<<"Member of class D "<<endl ; }  
  7.     void fun( ) const { cout<<"function of D "<<endl; }  
  8.   
  9. };  
  10.   
  11. int main(array<System::String ^> ^args)  
  12. {  
  13.     D tmp( 10, 20, 30, 40 );  
  14.     tmp.fun( );    
  15.     tmp.fun( );    
  16.     tmp.B::fun( );    
  17.     tmp.C::fun( );  
  18.   
  19.     system("pause");  
  20.     return 0;  
  21. }  

##注意,此时第三继承类对象tmp调用的成员函数统一都为fun()了;没有特例D::fun_d( )了。下面来区分下调用机制。

 

首先来看tmp.B::fun();

            tmp.C::fun(); //这里和前面的访问机制是一样的,不在赘述。

 

重点来看tmp.fun();不加所属类限定域时。回顾一下,当我们在局部区域定义一个和全局区域同名的变量时,当程序进入局部区域时,是如

 

何区分同名混淆的问题就知道。当程序查找fun()是在那个区域被定义过时,首先从局部区域出发,如果局部区域没有,向前查找,若一直未查找到,编译器会提示出错。这里程序首先就发现了D::fun().查找成功,边不再向前查找了

 

##运行结果:

运行结果

 

##下面来看,动态编译时,系统如何区分基类和派生类中出现同名成员函数的问题,依旧使用上面的例子,略作修改:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include<iostream>  
  3. using namespace std;  
  4. class A  
  5. {  
  6. private:  
  7.     int a_value ;  
  8. public:  
  9.     A( int a ):a_value(a){ cout<<"Member of class A"<<endl ;}  
  10.     virtual void fun( )const { cout<<"function of A"<<endl; }  
  11. };  
  12. class B : virtual public A  
  13. {  
  14. private:  
  15.     int b_value;  
  16. public:  
  17.     B( int a ,int b  ) : A(a),b_value(b){ cout<<"Member of class B "<<endl ;}  
  18.     void fun( )const { cout<<"function of B"<<endl; }  
  19. };  
  20. class C : virtual public A  
  21. {  
  22. private:  
  23.     int c_value ;  
  24. public:  
  25.     C( int a , int c ) : A(a),c_value(c){ cout<<"Member of class C "<<endl; }  
  26.     void fun( )const { cout<<"function of C"<<endl; }  
  27. };  
  28. class D :public B, public C  
  29. {  
  30. private:  
  31.     int d_value;  
  32. public:  
  33.     D( int a , int b , int c ,int d ) : A(a),B(a,b),C( a,c ),d_value( d ){ cout<<"Member of class D "<<endl ; }  
  34.     void fun( ) const { cout<<"function of D "<<endl; }  
  35.   
  36. };  
  37. const int Lim=4;  
  38. int main(array<System::String ^> ^args)  
  39. {  
  40.   A  first( 10 );  
  41.   B  second( 20,30 );  
  42.   C  third( 30, 40  );  
  43.   D  fouth( 60, 70, 80, 90);  
  44.   A *po[Lim]={ &first, &second, &third, &fouth };  
  45.   for ( int i=0;  i<Lim; i++ )  
  46.       po[i]->fun( );  
  47.   
  48.     system("pause");  
  49.     return 0;  
  50. }  

##现在来看,在基类A中出现了virtual void fun( )const ; 这就是本片段的重点:虚函数(实现动态编译的基础)。

 

当派生类中出现功能与基类中功能相近的函数调用时,我们就可以把基类中该函数设置成虚函数,在派生类中直接显示调用基类的这个功能

 

函数,然后添加本函数(即派生类)中需要独立实现的功能语句,以此类推,第三派生,第四派生,等等。当然最好使用公有派生,这样可

 

以高效的实现代码重用。

 

##下面切换到具体问题上具体分析:

首先来看主函数:

const int Lim=4;
int main(array<System::String ^> ^args)
{
  A  first( 10 );
  B  second( 20,30 );
  C  third( 30, 40  );
  D  fouth( 60, 70, 80, 90);
  A *po[Lim]={ &first, &second, &third, &fouth };
  for ( int i=0;  i<Lim; i++ )
   po[i]->fun( );

 system("pause");
    return 0;
}

1、首先显式构建了基类,第二派生类(两个),第三派生类(D)的四个对象first,second,third,fouth.并且声明了一个基类指针数组(顾

 

名思义:数组p0[Lim]里面保存的是四个指针,什么指针?指向基类和三个派生类对象地址的指针,根据C++派生类对象可以向上转换成基

 

类对象原则(附注:向下转换是不理智的,因为派生类可能新增加了新的成员,而这些基类是不具备的) ) 。然后显式调用函数fun(),

 

(注意: 在基类中fun()被声明为虚函数,所以在派生类中同名函数前可不比添加virtual关键字,这个系统内部是会区分的)根据虚函数调

 

用原则,例:po[i]->fun() /*当i=2时,这时候po(2)==&third */,系统将根据指针所指向的对象的类型来选择调用哪个函数,而不是根

 

据指针的类型来判断,所以这里将调用C::fun( )。以此类推,当i=0,1,2,3时以此对调用属于类A,B,C,D中的fun()函数。

 

下面是运行结果:

运行结果

##分析下运行结果,首先只看运行结果的前9行:

1、构建A的对象first时将显示Member of class A 这个显而易见。

 

 

2、构建B,C类的各自对象时,都将分别先调用各自基类的构造函数,在这里是A(基类),然后调用本类的构造函数,来初始化本类所新增加的成员,所以结果的2,3,4,5行就很明确了。

 

3、下面是构建类D的对象fouth时,由于类D是从类B,C中抽象出来的,所以生成类D的对象必然会调用类B,,C的构造函数来初始化类D继

 

承而来的成员,所以类B , C 都用的虚拟继承类A,这样类D构建对象时就不会再调用类B  ,C  时两次调用类A了。


来自:http://blog.csdn.net/free_program_1314/article/details/6548325

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值