第54课 被遗弃的多重继承(下)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第54课 被遗弃的多重继承(下)相关的知识,希望对你有一定的参考价值。
1. C++中的多重继承
(1)一个子类可以拥有多个父类
(2)子类拥有所有父类的成员变量
(3)子类继承所有父类的成员函数
(4)子类对象可以当作任意父类对象使用
(5)多重继承的语法规则
class Derived: public BaseA, public BaseB, public BaseC{…};
2. 多重继承问题一
(1)通过多重继承得到的对象可以拥有“不同的地址”!!!
(2)解释方案:无
(3)原因分析
【编程实验】多重继承问题一
#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; //12 Derived d(1, 2, 3); d.print(); cout << "d.getA() = " << d.getA() << endl; //1 cout << "d.getB() = " << d.getB() << endl; //2 cout << "d.getC() = " << d.getC() << endl; //3 cout << endl; BaseA* pa = &d; BaseB* pb = &d;//注意以上两行,都是将对象d的地址赋值给一个指针 //表面上看似pa指针应该等于pb指针,但实际上不会这样 //pa指向的是d对象中BaseA的子对象,而pb指向的是d //对象中BaseB子对象的部分。 cout << "pa = " << pa << endl; //0x23fe9c cout << "pb = " << pb << endl; //0x23fea0 void* paa = pa; void* pbb = pb; if(paa == pbb) { cout <<"point to the same object!" << endl; } else { cout << "Error" << endl; //该行被输出! } cout << "paa = " << paa << endl; //0x23fe9c cout << "pbb = " << pbb << endl; //0x23fea0 return 0; }
3. 多重继承问题二:可能产生冗余的成员
(1)当多重继承关系出现闭合时将产生数据冗余的问题!!!
(2)解决方案:虚继承
①虚继承能够解决数据冗余问题
②中间层父类不用再关心顶层父类的初始化
③最终子类必须直接调用顶层父类的构造函数
(3)存在问题:当架构设计中需要继承时,无法确定使用直接继承还是虚继承!!
【编程实验】多重继承问题二
#include <iostream> #include <string> using namespace std; class People { string mName; int mAge; public: People(string name, int age) { mName = name; mAge = age; } void print() { cout << "Name = " << mName << ", " << "Age = " << mAge << 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) { } }; //博士类(一个博士可能即是老师,又是学生),采用直接继承 //如果中间层的Teacher和Student不采用虚继承的话,那在Doctor //类中将有来自People类的mName、mAge等成员变量各两份,出现数据 //冗余现象,而且在子类Doctor中,如果直接mName = 1,会出现二义性的错误 //因为编译器不知道mName是来自Teacher类的还是Student类的 class Doctor: public Teacher, public Student { public: //请注意,构造函数中的最后一个初始化People,也就是说采用虚继承的话,则 //最终的子终仍需调用顶层父类的构造函数,这也是虚继承的一大问题,因为在 //实际开发中,有时很难确定最顶层的基类 Doctor(string name, int age):Teacher(name,age),Student(name,age),People(name,age) { } }; int main() { Doctor d("SantaClaus", 25); d.print(); return 0; }
4. 多重继承可能产生多个虚函数表
【编程实验】多重继承问题三
(1)当类中存在虚函数表时,如果需要进行强制类型转换时,C++中推荐使用新式类型转换关键字!!!
(2)解决方案:dynamic_cast
5. 正确的使用多重继承
(1)工程开发中的“多重继承”方式:单继承+多接口。
(2)一些有用的工程建议:
①先继承自一个父类,然后实现多个接口
②父类提供equal()成员函数,用于判断指针是否指向当前对象
③与多重继承相关的强制类型转换用dynamic_cast完成
【编程实验】正确的多继承方式
6. 小结
(1)C++支持多重继承的编程方式
(2)多重继承容易带来问题,如“同一个对象的地址不同”、“数据冗余”问题等。
(3)多继承中可能出现多个虚函数表指针
(4)与多重继承相关的强制类型转换用dynamic_cast完成
(5)工程开发中采用“单继承+多接口”的方式使用多继承
(6)父类提供成员函数用于判断指针是否指向当前对象
以上是关于第54课 被遗弃的多重继承(下)的主要内容,如果未能解决你的问题,请参考以下文章