• C++代码重用(二)


    多重继承

    多重继承描述的是有多个直接基类的类,与单继承一样,公有多重继承表示的都是is-a的关系。而私有多重继承和保护多重继承表示的是has-a的关系。

    下面我们看一个例子:

    class Base{...};
    class BaseA : public Base{...};
    class BaseB : public Base{...};
    class Abc : public BaseApublic BaseB{...};
    
    ···
    
    Abc abc;
    Base * base = &abc;  //将出现二义性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    针对上例,类Abc多重继承了BaseABaseB两个类,由于BaseABaseB都继承了Base,因此Abc包含了两个Base组件,因此在将派生类类对象的地址赋值给基类指针的时候,会出现二义性。abc包含两个Base对象,有两个地址可供选择,所以可以使用类型转换来指定对象:

    Base * base1 = (BaseA*)&abc;
    Base * base2 = (BaseB*)&abc;
    
    • 1
    • 2

    这样虽然可以解决上例子带来的二义性,但使得使用基类指针来引用不同的对象(多态性)复杂化。而且实际应用中Abc类也不需要包含两个Base对象。因此c++引入了虚基类的概念来解决该情况下的多重继承。

    虚基类使得从多个类(他们的基类相同)派生出来的对象只继承一个基类对象。具体的做法如下:

    class Base{...};
    class BaseA : virtual public Base{...};
    class BaseB : public virtual Base{...}; //virtual与public的顺序不做要求,两种写法都是对的
    class Abc : public BaseApublic BaseB{...};
    
    • 1
    • 2
    • 3
    • 4

    这样做可以保证Abc类对象中只会包含Base类对象的一个副本。从本质上讲,应该是继承的BaseABaseB类对象共享了一个Base对象。这样就可以简单的使用多态。

    针对虚基类,在设计的时候需要对其类构造函数采用一种新的方法。例如:

    class Base{
        int base;
        public:
        Base(int ba = 0):base(ba){}};
    
    class BaseA : virtual public Base{
        int a;
        public:
        BaseA(int a = 0,int ba = 0): Base(ba),a(a){}
    };
    
    class BaseB : virtual public Base{
        int b;
        public:
        BaseC(int b = 0,int ba = 0): Base(ba),b(b) {}
    }; 
    
    class Abc : public BaseApublic BaseB{
        int abc;
        public:
        Abc(int a = 0,int b = 0,int ba = 0; int abc = 0):BaseA(a, ba), BaseB(b, ba), abc(abc){}// flawed
        Abc(int a = 0,int b = 0,int ba = 0; int abc = 0):Base(ba), BaseA(a, ba), BaseB(b, ba), abc(abc){}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    其中,对于:

    Abc(int a = 0,int b = 0,int ba = 0; int abc = 0):BaseA(a, ba), BaseB(b, ba), abc(abc){}// flawed
    
    • 1

    Base是虚基类的时候,Abc类通过BaseABaseB的构造函数将参数信息间接传递给Base时将不起作用,c++在基类是虚的时候,禁止将参数信息通过中间类传递给基类。因此上述ba的信息必不能传递给子对象Base,然而编译器会使用Base的默认构造函数,在构造派生类对象之前构造基类对象组件。如果不希望使用默认构造函数来构造虚基类函对象,则需要显式地调用基类构造函数。因此构造函数如下:

    Abc(int a = 0,int b = 0,int ba = 0; int abc = 0):Base(ba), BaseA(a, ba), BaseB(b, ba), abc(abc){}
    
    • 1

    :上述代码显式地调用Base的构造函数,是合法的,但是对于非虚基类,则是非法的。)

    如果类有间接虚基类,则除非只使用该虚基类的默认构造函数,否则必须显式地调用该虚基类的某个构造函数。

  • 相关阅读:
    #ACCV2022还有两周截稿#疫情过后期待相聚澳门,相邀参与亚洲视觉盛会
    ORA-17002 IP hostname timeout DISTRIBUTED_LOCK_TIMEOUT
    AQS中 state 和 waitStatus 分别是干什么的?
    Android so库中UnsatisfiedLinkError
    搞脑筋的日历积木
    详解 docker save 与 docker export 的区别
    毕业设计选题之Android基于移动端的线上订餐app外卖点餐安卓系统源码 调试 开题 lw
    【UCIe】UCIe Runtime Link Test Using Parity
    C# 从代码入门 Mysql 数据库事务
    Flutter “No implementation found for method xxxx on channel
  • 原文地址:https://blog.csdn.net/jianmo1993/article/details/128118840