1访问从基类继承的成员
当派生类与基类中有相同成员时:
若未特别限定,则通过派生类对象使用的是派生类中的同名成员。
如要通过派生类对象访问基类中被隐藏的同名成员,应使用基类名和作用域操作符(::)来限定。
//7-6多继承同名隐藏举例 #include<iostream> using namespace std; class Base1{ public: int var; void fun(){cout << "Member of Base1" << endl;} }; class Base2{ public: int var; void fun(){cout << "Member of Base2" << endl;} }; class Derived: public Base1, public Base2{ public: int var; void fun(){cout << "Member of Derived" << endl;} }; int main(){ Derived d; Derived *p = &d; d.var = 1;//访问Derived类成员 d.fun(); d.Base1::var = 2; d.Base1::fun(); p->Base2::var = 3; p->Base2::fun(); return 0; }
//7-7多继承时的二义性和冗余问题 #include<iostream> using namespace std; class Base0{ public: int var0; void fun0(){cout << "Member of Base0" << endl;} }; class Base1: public Base0 { public: int var1; }; class Base2: public Base0{ public: int var2; }; class Derived: public Base1, public Base2{ public: int var; void fun(){cout << "Member of Derived" << endl;} }; int main(){ Derived d; d.Base1::var0 = 2; d.Base1::fun0(); d.Base2::var0 = 3; d.Base2::fun0(); return 0; }
Derived类对象d的存储结构示意图1
2虚基类
需要解决的问题
当派生类从多个基类派生,而这些基类又共同基类,则在访问此共同基类中的成员时,将产生冗余,并有可能因冗余带来不一致性
虚基类声明
以virtual说明基类继承方式
例:class B1:virtual public B
作用
主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题
为最远的派生类提供唯一的基类成员,而不重复产生多次复制
注意:
在第一级继承时就要将共同基类设计为虚基类。
虚基类举例2:
//例7-8 虚基类举例 #include<iostream> using namespace std; class Base0{ public: int var0; void fun0(){cout << "Member of Base0" << endl;} }; class Base1:virtual public Base0{ public: int var1; }; class Base2:virtual public Base0{ public: int var2; }; class Derived: public Base1, public Base2{ public: int var; void fun(){ cout << "Member of Derived" << endl; } }; int main(){ Derived d; d.var0 = 2;//直接访问虚基类的数据成员 d.fun0();//直接访问虚基类的函数成员 return 0; }
虚基类及其派生类构造函数:
建立对象时所指定的类称为最远派生类。
虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中为虚基类的构造函数列出参数。
如果未列出,则表示调用该虚基类的默认构造函数。
在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略。
//有虚基类时的构造函数举例(补7-4) #include<iostream> using namespace std; class Base0{ public: Base0(int var):var0(var){} int var0; void fun0(){cout << "Member of Base0" << endl;} }; class Base1: virtual public Base0{ public: Base1(int var):Base0(var){} int var1; }; class Base2: virtual public Base0{ public: Base2(int var):Base0(var){} int var2; }; class Derived: public Base1, public Base2{ public: Derived(int var):Base0(var), Base1(var), Base2(var){} int var; void fun(){ cout << "Member of Derived" << endl; } }; int main(){ Derived d(1); d.var0 = 2; d.fun0(); return 0; }