二义性
- 在多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)——采用虚函数或同名隐藏规则来解决。
- 当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性——采用虚基类来解决。
class A {
public:
void f();
};
class B {
public:
void f();
void g();
};
class C : public A, public B {
public:
void g();
void h();
};
如果定义:C c1;
则c1.f() 具有二义性
而c1.g() 无二义性(同名隐藏)
解决方法一:用类名来限定c1.A::f() 或c1.B::f()
解决方法二:同名隐藏在C 中声明一个同名成员函数f(),f()再根据需要调用A::f() 或B::f()
虚基类- 虚基类的引入:用于有共同基类的场合
- 声明:以virtual修饰说明基类例:class B1:virtual public B
- 作用:1、主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题。2、为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝
- 注意:在第一级继承时就要将共同基类设计为虚基类。
#include <iostream>
using namespace std;
class Base0 { //定义基类Base0
public:
int var0;
void fun0() { cout << "Member of Base0" << endl; }
};
class Base1 : virtual public Base0 { //定义派生类Base1
public: //新增外部接口
int var1;
};
class Base2 : virtual public Base0 { //定义派生类Base2
public: //新增外部接口
int var2;
};
class Derived : public Base1, public Base2 { //定义派生类Derived
public: //新增外部接口
int var;
void fun() {
cout << "Member of Derived" << endl;
}
};
int main() //程序主函数
{
Derived d; //定义Derived类对象d
d.var0 = 2; //直接访问虚基类的数据成员
d.fun0(); //直接访问虚基类的函数成员
return 0;
}
虚基类及其派生类构造函数
- 建立对象时所指定的类称为最(远)派生类;
- 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用;
- 在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,其他基类对虚基类构造函数的调用被忽略
#include <iostream>
using namespace std;
class Base0 { //定义基类Base0
public:
Base0(int var) : var0(var) { }
int var0;
void fun0() { cout << "Member of Base0" << endl; }
};
class Base1 : virtual public Base0 { //定义派生类Base1
public: //新增外部接口
Base1(int var) : Base0(var) { }
int var1;
};
class Base2 : virtual public Base0 { //定义派生类Base2
public: //新增外部接口
Base2(int var) : Base0(var) { }
int var2;
};
class Derived : public Base1, public Base2 { //定义派生类Derived
public: //新增外部接口
Derived(int cvar) : Base0(var), Base1(var), Base2(var) { }
int var;
void fun() { cout << "Member of Derived" << endl; }
};
int main() { //程序主函数
Derived d(1); //定义Derived类对象d
d.var0 = 2; //直接访问虚基类的数据成员
d.fun0(); //直接访问虚基类的函数成员
return 0;
}