zoukankan      html  css  js  c++  java
  • C++虚类的作用(转)

    虚基类的作用

         
    当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份。例如:
    class CBase { };
    class CDerive1:virtual public CBase{ };
    class CDerive2:virtual public CBase{ };
    class CDerive12:public CDerive1,CDerive2{ };
    则在类CDerive12的对象中,仅有类CBase的一个对象数据

    虚基类的特点:
           虚基类构造函数的参数必须由最新派生出来的类负责初始化(即使不是直接继承);
           虚基类的构造函数先于非虚基类的构造函数执行。
          
        
    重写“C++学习笔记(9)——使用范围运算符解决继承中的二义性问题 ”中的程序,观察虚基类的作用
    代码如下:
          
    /**//************************************************************************
    * 混合继承:多基类继承与多重继承
    ***********************************************************************
    */

    #include 
    <IOSTREAM.H>
    //基类
    class CBase
    ...
    {
    protected
    :
        
    int
     a;
    public
    :
        CBase(
    int
     na)
        
    ...
    {
            a
    =
    na;
            cout
    <<"CBase constructor! "
    ;
        }


        
    ~CBase()...{cout<<"CBase deconstructor! ";}
    }
    ;

    //派生类1(声明CBase为虚基类)

    class CDerive1:virtual public CBase
    ...
    {
    public
    :
        CDerive1(
    int
     na):CBase(na)
        
    ...
    {
            cout
    <<"CDerive1 constructor! "
    ;
        }

        
        
    ~CDerive1()...{cout<<"CDerive1 deconstructor! ";}

        
    int GetA()...{return a;}
    }
    ;

    //派生类2(声明CBase为虚基类)

    class CDerive2:virtual public CBase
    ...
    {
    public
    :
        CDerive2(
    int
     na):CBase(na)
        
    ...
    {
            cout
    <<"CDerive2 constructor! "
    ;
        }

        
    ~CDerive2()...{cout<<"CDerive2 deconstructor! ";}
        
    int GetA()...{return a;}
    }
    ;

    //子派生类

    class CDerive12:public CDerive1,public CDerive2
    ...
    {
    public
    :
        CDerive12(
    int na1,int na2,int
     na3):CDerive1(na1),CDerive2(na2),CBase(na3)
        
    ...
    {
            cout
    <<"CDerive12 constructor! "
    ;
        }

        
    ~CDerive12()...{cout<<"CDerive12 deconstructor! ";}
    }
    ;
    void
     main()
    ...
    {
        CDerive12 obj(
    100,200,300
    );
        
    //得到从CDerive1继承的值

        cout<<" from CDerive1 : a = "<<obj.CDerive1::GetA();
        
    //得到从CDerive2继承的值

        cout<<" from CDerive2 : a = "<<obj.CDerive2::GetA()<<endl<<endl;
    }
              
           
    1. 子派生类对象的值:
          
                 
         从上例可以看出,在类CDerived12的构造函数初始化表中,调用了间接基类CBase的构造函数,这对于非虚基类是非法的,但对于虚基类则是合法且必要的。
      对于派生类CDerived1和CDerived2,不论是其内部实现,还是实例化的对象,基类CBase是否是它们的虚基类是没有影响的。受到影响的是它们的派生类CDerived12,因为它从两条路径都能到达CBase。
            
    2. 运行结果:
                
                  
        由此可知,其公共基类的构造函数只调用了一次,并且优先于非基类的构造函数调用;并且发现,子派生类的对象obj的成员变量的值只有一个,所以,当公共基类CBase被声明为虚基类后,虽然它成为CDerive1和CDerive2的公共基类,但子派生类CDerive12中也只有它的一个备份。可以仔细比较与例2的运行结果有什么不同。 
  • 相关阅读:
    LeetCode(111) Minimum Depth of Binary Tree
    LeetCode(108) Convert Sorted Array to Binary Search Tree
    LeetCode(106) Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode(105) Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode(99) Recover Binary Search Tree
    【Android】通过经纬度查询城市信息
    【Android】自定义View
    【OpenStack Cinder】Cinder安装时遇到的一些坑
    【积淀】半夜突然有点想法
    【Android】 HttpClient 发送REST请求
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2857241.html
Copyright © 2011-2022 走看看