【C++深度解析】38、被遗弃的多重继承
程序员文章站
2022-05-29 17:49:11
...
1 何为多重继承
C++允许一个类拥有多个父类,这就是多重继承
- 子类拥有所有父类的成员变量
- 子类继承所有父类的成员函数
- 子类对象可以当作任意父类对象使用
多重继承的语法规则:
// 38-1.cpp
#include<iostream>
using namespace std;
class BaseA
{
int ma;
public:
BaseA(int a) { ma = a; }
int getA() { return ma; }
};
class BaseB
{
int mb;
public:
BaseB(int b) { mb = b; }
int getB() { return mb; }
};
class Derived : public BaseA, public BaseB
{
int mc;
public:
Derived(int a, int b, int c) : BaseA(a), BaseB(b)
{
mc = c;
}
int getC() { return mc; }
void print()
{
cout << "ma = " << getA() << ", "
<<"mb = " << getB() << ", "
<< "mc = " << mc << endl;
}
};
int main()
{
cout << "sizeof(Derived) = " << sizeof(Derived) << endl;
Derived d(1, 2, 3);
d.print();
cout << "d.getA() = " << d.getA() << endl;
cout << "d.getB() = " << d.getB() << endl;
cout << "d.getC() = " << d.getC() << endl;
cout << endl;
BaseA* pa = &d;
BaseB* pb = &d;
cout << "pa->getA() = " << pa->getA() << endl;
cout << "pb->getB() = " << pb->getB() << endl;
cout << endl;
cout << "pa = " << pa << endl;
cout << "pb = " << pb << endl;
return 0;
}
- 类 Derived 继承了类 BaseA 和类 BaseB,子类是由父类成员叠加子类得到的,所以类 Derived 拥有成员变量 ma,mb,mc。计算类对象大小时,计算的是成员变量的大小,成员函数保存在代码段,不计入对象大小。所以类 Derived 大小为 12。
- Derived 对象可以调用继承来的成员函数 getA() ,getB()
- 子类对象可以转换为任意父类对象使用,所以程序第 46-50 行可以转换为两个父类对象,调用父类函数
- 程序第 53-54行打印指向对象 d 的两个指针来说明多重继承的第一个问题
编译运行:
$ g++ 38-1.cpp -o 38-1
$ ./38-1
sizeof(Derived) = 12
ma = 1, mb = 2, mc = 3
d.getA() = 1
d.getB() = 2
d.getC() = 3
pa->getA() = 1
pb->getB() = 2
pa = 0x7ffee3d7e03c
pb = 0x7ffee3d7e040
运行结果和我们分析的一致,但是 pa,pb 都是指向对象 d 的指针,他们的值却不同。这就是第一个问题。
2 多重继承问题一
- 通过多重继承得到的对象可能拥有“不同的地址”
如下图所示,两个指针指向一个对象,可能指向的位置不同,且目前没有解决方案。
3 多重继承问题二
- 多重继承可能产生冗余的成员
当多重继承关系出现闭合时产生数据冗余的问题
解决方案:虚继承
- 虚继承能够解决数据冗问题
- 中间层父类不再关心顶层父类的初始化
- 最终子类必须直接调用顶层父类的构造函数
#include <iostream>
#include <string>
using namespace std;
class People
{
string m_name;
int m_age;
public:
People(string name, int age)
{
m_name = name;
m_age = age;
}
void print()
{
cout << "Name = " << m_name << ", "
<< "Age = " << m_age << endl;
}
};
class Teacher : virtual public People // 虚继承
{
public:
Teacher(string name, int age) : People(name, age)
{
}
};
class Student : virtual public People // 虚继承
{
public:
Student(string name, int age) : People(name, age)
{
}
};
class Doctor : public Teacher, public Student
{
public:
// 最终子类必须直接调用顶层父类的构造函数
Doctor(string name, int age) : Teacher(name, age), Student(name, age), People(name, age)
{
}
};
int main()
{
Doctor d("Delphi", 33);
d.print();
return 0;
}
4 小结
1、C++支持多重继承的编程方式
2、多重继承的问题
- 可能出现同一个对象地址不同的情况
- 虚继承可以解决数据冗余的问题