多继承同名问题
看下面代码 Derived类继承了Base1和Base2 这三个类有着同名的成员变量var和成员函数fun()
#include <iostream>
using namespace std;
class Base1 {
public:
int var;
void fun() { cout << "Member of Base1, var is " << var << endl; }
};
class Base2 {
public:
int var;
void fun() { cout << "Member of Base2, var is " << var << endl; }
};
class Derived :public Base1, public Base2 {
public:
int var;
void fun() { cout << "Member of Derived, var is " << var << endl;}
};
那现在我们怎么访问Derived、Base1和Base2的成员?
当我们访问Derived成员的时候 很简单 使用Derived对象名或引用名.成员 或 Derived指针->成员即可
int main()
{
Derived d;
Derived* p = &d;
Derived& dd = d;
//访问Derived类成员
d.var = 1;
d.fun();
p->var = 2;
p->fun();
dd.var = 3;
dd.fun();
return 0;
}
编译运行
通过调试可以发现 d.var就是Derived类自己的成员var 而不是基类的var 此时基类Base1和Base2的var是未定义的值
当我们想要访问派生类继承过来的非同名成员时 只需要直接调用即可
那怎么通过Derived对象或指针访问Base1、Base2的同名成员呢?
使用类名限定
访问从基类继承来的同名成员时 带上类名就可以了
int main()
{
Derived d;
Derived* p = &d;
//访问Derived类成员
d.var = 1;
d.fun();
p->var = 2;
p->fun();
//访问Base1基类成员
d.Base1::var = 2;
d.Base1::fun();
//访问Base2基类成员
p->Base2::var = 3;
p->Base2::fun();
return 0;
}
编译运行
调试验证一下
多继承二义性、冗余问题
二义性:如果从不同基类继承了同名的成员 但是在派生类中没有定义同名成员 使用 "派生类对象名或引用名.成员名" 、"派生类指针->成员名" 访问成员存在二义性问题
看下面代码 Derived类继承了Base1和Base2 Base1和Base2都继承了Base0
此时Derived类继承过来了两个不同的var0 且 Derived类没有定义var0变量
想要通过Derived类的对象访问var0时 不能通过上述操作来访问了 会造成二义性问题
#include <iostream>
using namespace std;
class Base0 {
public:
int var0;
void fun0() { cout << "Member of Base0,var0 is " << var0 << 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();
d.Base1::fun0();
return 0;
}
想一想 输出是什么?
和你想的一样吗?是两个不同的var0 我们来调试下看看
创建Derived对象d 可以看到Derived类继承的Base1和Base2 都有一个var0
继续单步执行 可以看到Base1继承过来的var0值是2 而Base2继承过来的var0依然是未定义的值
继续执行
Base1和Base2各有一个var0 输出地址验证一下
int main()
{
Derived d;
d.Base1::var0 = 2;
d.Base1::fun0();
d.Base2::var0 = 3;
d.Base2::fun0();
d.Base1::fun0();
cout << &d.Base1::var0 << endl;
cout << &d.Base2::var0 << endl;
cout << &d.Base0::var0 << endl;
return 0;
}
果然 地址不一样 内存中有两个var0 其中Base0的var0和Base1的var0是同一个
这就造成了冗余和不一致性 怎么解决呢?
使用虚基类 也就是虚继承!!
虚基类
需要解决的问题
当派生类从多个基类派生 而这些基类有共同基类 则访问此共同基类中的成员时 将产生冗余 并有可能因冗余带来不一致性
虚基类声明
以virtual说明基类继承方式
例:class B1:virtual public B
作用
主要用来解决多继承时可能发生的对同一基类继承多次而产生的的二义性、冗余问题
为最远的派生类提供唯一的基类成员 而不重复产生多次复制
注意
在第一级继承时就要将共同基类设计为虚基类
#include <iostream>
using namespace std;
class Base0 {
public:
int var0;
void fun0() { cout << "Member of Base0,var0 is " << var0 << 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;
}
这个时候我们可以直接访问虚基类的数据成员和函数成员了
调试一下 发现d.var0执行完后 Base1和Base2和Base0的var0都变成了2
加上几句代码验证一下
int main()
{
Derived d;
d.var0 = 2;//直接访问虚基类的数据成员
d.fun0();//直接访问虚基类的函数成员
cout << &d.var0 << endl;
cout << &d.Base1::var0 << endl;
cout << &d.Base2::var0 << endl;
cout << &d.Base0::var0 << endl;
return 0;
}
发现地址都相同 说明内存中只有一份var0
接下一篇文章 https://blog.csdn.net/qq_39227517/article/details/123595107