访问从基类继承的成员
作用域限定
当派生类与基类中有相同成员时:
-
若未特别限定,则通过派生类对象使用的是派生类中的同名成员。
-
如要通过派生类对象访问基类中被隐藏的同名成员,应使用基类名和作用域操作符(::)来限定。
例7-6 多继承同名隐藏举例
#include <iostream>
using namespace std;
class Base1{
public:
int var;
void fun(){
cout << "Member of Base1: " << var <<endl;
}
};
class Base2{
public:
int var;
void fun(){
cout << "Member of Base2: " << var <<endl;
}
};
class Derived:public Base1,public Base2{
//派生新类Derived,注意基类名的顺序
public:
int var;
void fun(){
cout << "Member of Derived: " << var << endl;
}
};
int main() { //主函数
Derived d;
Derived* p= &d;
//访问Derived类成员
d.var = 1;
d.fun();
//访问Base1中的类成员
d.Base1::var = 2;
d.Base1::fun();
//访问Base2中的类成员
p->Base2::var = 3;
p->Base2::fun();
return 0;
}
二义性问题
-
如果从不同基类继承了同名成员,但是在派生类中没有定义同名成员,“派生类对象名或引用名.成员名”、“派生类指针->成员名”访问成员存在二义性问题
-
解决方式:用类名限定
问题:二义性带来的冗余问题
解决办法:虚基类
虚基类
需要解决的问题
- 当派生类从多个基类派生,而这些基类有共同基类,则在访问此共同基类中的成员时,将产生冗余,并有可能因冗余带来不一致性
虚基类声明
- 以virtual说明基类继承方式
- 例: class B1:virtual public B
作用
- 主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题
- 为最远的派生类提供唯一的基类成员,而不重复产生多次复制
注意:
- 第一级继承时就要将共同基类设计为虚基类。
例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 {
//定义派生类Derived
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;
}