• 虚基类的作用:消除二义性


    前因:

    1.C++中多重继承,即一个派生类可以有多个基类。如果多个基类有同名成员或同名函数,派生类对象对其访问时会产生二义性。

    举例:

    #include <iostream>
    using namespace std;
    
    class Base1    
    {        
    public:                                                
        Base1(int var){cout << "Base1" << endl; };
        int var;
        void fun() { cout << "Base1::fun()" << endl; }
    };
     
    class Base2            
    {
    public:                                                
        Base2(int var){cout << "Base2" << endl;};
        int var;
        void fun() { cout << "Base2::fun()" << endl; }
    };
     
    class Derived : public Base1, public Base2 {        
    public:                                                
        Derived(int var) : Base1(var), Base2(var){cout << "Derived" << endl; };
        //int var;
        //void fun() { cout << "Derived::fun()" << endl; }
    };
     
    int main() {                                    
        Derived d(1);                                
        d.var = 2;                                    
        d.fun();
        //cout<<"d.var = " <<d.var<<endl;
        return 0;
    }
    View Code

    输出:

    2.如果多个基类又有一个共同的基类,则在最终的派生类中会保留多份同名的共同基类的数据成员。

    避免二义性的访问方法:  c.A::display( );

    为了避免派生类中保留多份同名成员,C++提供了虚基类(virtual base class)的方法,在派生类中只保留一份成员。

    声明:class 派生类名: virtual 继承方式 基类名

    Class A    //声明基类A

    {...};

    Class B1 : virtual public A  //声明派生类B1,A是B1的虚基类

    {...};

    Class B2 : virtual public A  //声明派生类B2,A是B2的虚基类

    {...};

    Class C : public B1, public B2  //声明派生类C,多继承B1和B2,只继承A一次

    {...};

    注意: 
    虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。因为一个基类可以在生成一个派生类时作为虚基类,而在生成另一个派生类时不作为虚基类。

    实例:

    #include <iostream>
    using namespace std;
    
    class Base0 {                                        
    public:
        Base0(int var) : var0(var) { cout << "Base0" << endl;};
        int var0;
        void fun0() { cout << "Member of Base0" << endl; }
    };
     
    class Base1 : virtual public Base0 {                
    public:                                                
        Base1(int var) : Base0(var){cout << "Base1" << endl; };
        int var1;
    };
     
    class Base2 : virtual public Base0 {                
    public:                                                
        Base2(int var) : Base0(var){cout << "Base2" << endl;};
        int var2;
    };
     
    class Derived : public Base1, public Base2 {        
    public:                                                
        Derived(int var) : Base0(var), Base1(var), Base2(var), var(0){cout << "Derived" << endl; };
        int var;
        void fun() { cout << "Member of Derived" << endl; }
    };
     
    int main() {                                    
        Derived d(1);                                
        d.var0 = 2;                                    
        d.fun0();    
        cout<<"d.var0 = " <<d.var0<<endl;
        cout<<"d.var1 = " <<d.var1<<endl;
        cout<<"d.var2 = " <<d.var2<<endl;
        cout<<"d.var = "  <<d.var<<endl;
        return 0;
    }
    View Code

    输出:

    注意:

    1.在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用;

    2.在建立对象时,只有最后派生类的构造函数调用虚基类的构造函数,而忽略虚基类的其他派生类,这样就保证了虚基类的数据成员不会被多次初始化。

    参考来源:

    https://www.cnblogs.com/yiranlaobaitu/p/3764422.html

    https://blog.csdn.net/happyjacob/article/details/80781093

    PS:

    https://blog.csdn.net/qq_28114615/article/details/88077009  这篇博客介绍了虚继承的内存分布,非常详细

  • 相关阅读:
    商业模式--资源整合
    “不小心出卖了领导”
    计算机禁用桌面并且禁用键盘Win+*快捷键组合之后如何打开文件资源管理器
    spring-boot 参数长度、文件上传大小限制问题
    Python 学习基础
    Python字典详解
    Python元组
    Python列表详解
    Python变量类型
    Python字符串详解
  • 原文地址:https://www.cnblogs.com/Brickert/p/10705236.html
Copyright © 2020-2023  润新知