多继承的二义性:
问题产生:一个派生类有两个或以上的基类(A B)其中A和B中有相同的成员名称或接口名称, 当派生类想调用时产生二义性
(这里的二义性是指无法直接通过变量名进行读取),需要通过域(::)成员运算符进行区分
C.A::m_a = 10;
C.B::m_a = 15;
菱形继承问题
问题产生:一个派生类有两个或以上的基类,这些基类中存在相同的基类即(B继承A C继承A D继承B和C) 当派生类想要直接调用A类中的方法时,产生二义性。 这里的二义性是由于他们间接都有相同的基类导致的,除了带来二义性外,还会浪费空间(每个派生类中都会带有一份基类的内存)
虚基类:为了解决菱形继承带来的问题,C++引入了虚基类 其作用为在间接继承共同基类时只保存一份基类成员,
虚基类声明: class A{}; class B : virtual public A{}; class C :virtual public A{};
-->虚基类并不是在申明基类时声明的 而是在派生类时 指定继承方式声明的
虚基类的初始化:在派生类中对基类进行初始化还需要对虚基类进行初始化
如D继承自B和C:D构造函数时需要初始化虚基类 如 D() : B(), C(), A(xx) {}
C++编译器只执行最后的派生类对基类的构造函数的调用,而忽略其他派生类对基类的构造函数的调用,从而避免对基类数据成员重复初始化
多继承总结:
单继承:只有一个直接基类中产生派生类的能力
多继承:从多个直接基类中产生派生类的能力,派生类对象包含每个基类的子对象
菱形继承:产生二义性, 增加域名限定符进行区别
虚继承:解决问题:继承间接共同基类时只保留一份成员, 解决菱形继承时带来的基类对象重复问题
形式:class B :virtual public A
初始化:最后派生类中不仅要负责对其直接基类进行初始化还要对虚基类进行初始化, 中间类按照继承类进行初始化
虚基类:通过虚继承的方式派生的基类
重载:同一个类中, 函数名称相同,函数参数个数或者类型不同的函数
重写(覆盖):基类和派生类中,函数名称和函数参数都相同 基类中该函数为虚函数
隐藏:基类和派生类中, 如果和基类中函数名称相同但是参数不同 则不管基类中该函数是否为虚函数都将隐藏
如果和基类中函数名称相同参数也相同, 如果基类该函数不是虚函数则基类函数被隐藏