派生类成员的标识与访问
(1)若未特别限定,则通过派生类对象使用的是派生类中的同名成员
(2)如要通过派生类对象访问基类中被隐藏的同名成员,应使用基类名和作用域操作符(::)来限定
Ex:
#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;
//访问Derived类成员
d.var = 1;
d.fun();
//访问Base1基类成员
d.Base1::var = 2;
d.Base1::fun();
//访问Base2基类成员
p->Base2::var = 3;
p->Base2::fun();
return 0;
}
(1)如果从不同基类继承了同名成员,但是派生类中没有定义同名成员,"派生类对象名或引用名.成员名","派生类指针->成员名"访问成员存在二义性问题。
(2)解决方式:用类名来限定
Ex:如果定义 C c1;
则c1.f()具有二义性,而c1.g()无二义性(同名隐藏)
class A {
public:
void f();
};
class B {
public:
void f();
void g()
};
class C: public A, piblic B {
public:
void g();
void h();
};解决方法一:用类名来限定
c1.A::f() 或 c1.B::f()
解决方法二:同名隐藏
在C中声明一个同名成员函数f(),f()再根据需要调用A::f()或B::f()
EX:
#include <iostream>
using namespace std;
class Base0 { //定义基类Base0
public:
int var0;
void fun0() { cout << "Member of Base0" << endl; }
};
class Base1: public Base0 { //定义派生类Base1
public: //新增外部接口
int var1;
};
class Base2: public Base0 { //定义派生类Base2
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;
}
当派生类从多个基类派生,而这些基类又有共同基类,则在访问此共同基类中的成员时,将产生冗余,并有可能因冗余带来不一致性。
以virtual说明基类继承方式
例:class B1:virtual public B
(1)主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题
(2)为最远的派生类提供唯一的基类成员,而不重复产生多次复制
Ex:
#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;
}
(1)建立对象时所指定的类称为最远派生类
(2)虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化
(3)在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中为虚基类的构造函数列出参数。如果未列出,则表示调用该虚基类的默认构造函数。
(4)在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略。
Ex:
#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;
}