4.类型兼容
4.1 定义
在公有派生的情况下,一个派生类对象可作为基类的对象来使用
◼ 派生类对象可以赋值给基类对象
◼ 派生类对象可以初始化基类的引用
◼ 派生类对象的地址可赋给指向基类的指针
5. 多继承类
5.1 定义
#include <iostream> using namespace std; class CTopBase { protected: int a; public: CTopBase(int _a=0) { a=_a; cout << "Top base" << a << endl; } }; class CBase1:public CTopBase { int b; public: CBase1(int _a=0,int _b=0):CTopBase(_a) { b=_b; cout << "Base1" << b << endl; } }; class CBase2:public CTopBase { int c; public: CBase2(int _a=0,int _c=0):CTopBase(_a) { c=_c; cout << "Base2" << c << endl; } }; class CDerived:public CBase1,public CBase2 { public: CDerived(int _a=0,int _c=0,int _b=0):CBase1(_a,_b),CBase2(_a,_c) { cout << "derived" << endl; } }; int main() { CDerived obj(3,4,5); return 0; }
问题:顶级基类的构造函数会调用两次
5.2 构造与析构函数的调用顺序
◼ 调用各基类构造函数:调用顺序按基类被继承时声明的顺序,从左向右依次进行
◼ 调用派生类成员对象构造函数:调用顺序按其在类中定义的顺序依次执行
◼ 调用派生类构造函数
5.3 二义性
在上面的代码中,如果CBase1和CBase2中都有show()函数,Derived调用的时候就不知道是哪个
(request for member ‘show’ is ambiguous)
◼ 派生类的多个基类中拥有同名成员时,继承后通过对象调用同名成员将出现二义性
6.虚基类
6.1 定义
class 派生类名:virtual 继承方式 基类名
class CBase1: virtual public CTopBase
class CBase2: virtual public CTopBase
6.2 作用
虚基类构造函数只被调用一次:上面的结果是
调用一次,但结果为0(默认无参的构造函数),说明CTopBase函数不会被激活
手动更改,给参数:CDerived(int _a=0,int _c=0,int _b=0):CTopBase(_a),CBase1(_a,_b),CBase2(_a,_c)
◼ 在派生类建立对象时,先调用基类的构造函数,再调用派生类的构造函数
◼ 类型兼容是指在公有派生的情况下,一个派生类对象可以作为基类的对象来使用
◼ 多继承时,多个基类中的同名成员在派生类中由于标识符不唯一而出现二义性
◼ 在多继承中,当派生类的部分或全部直接基类又是从另一个共同基类派生而来时, 可能会出现间接二义性 → 虚基类
#include <iostream> #include <windows.h> #include <mmsystem.h> using namespace std; class CAnimal //基类 { string name; int age; int weight; public: CAnimal(string strName="", int a=0, int w=0) { name = strName; age = a; weight = w; cout << "Animal constructor " << name << endl; } void Show() { cout << name << " " << age << " " << weight << endl; } ~CAnimal() { cout << "Animal destructor " << name << endl; } }; class CBird: virtual public CAnimal //派生类1 { int wingSpan; public: CBird(int ws=0, string strName="", int a=0, int w=0):CAnimal(strName, a, w) { wingSpan = ws; cout << "Bird constructor " << endl; } void Show() { CAnimal::Show(); cout << "Wingspan:" << wingSpan << endl; } void Fly() { cout << "I can fly! I can fly!!" << endl; } void Talk() { cout << "Chirp..." << endl; PlaySound(".\sound\eagle.wav",NULL, SND_FILENAME|SND_SYNC); } ~CBird() { cout << "Bird destructor " << endl; } }; class CHorse: virtual public CAnimal //派生类2 { int power; public: CHorse(int pow=0, string strName="", int a=0, int w=0):CAnimal(strName, a, w) { power = pow; cout << "Horse constructor " << endl; } void Show() { CAnimal::Show(); cout << "Power:" << power << endl; } void Run() { cout << "I can run! I run because I love to!!" << endl; //emmm } void Talk() { cout << "Whinny!..." << endl; PlaySound(".\sound\horse.wav",NULL, SND_FILENAME|SND_SYNC); } ~CHorse() { cout << "Horse destructor " << endl; } }; class CPegasus: public CHorse, public CBird //派生类1&2,无virtual了 { public: CPegasus(string strName="", int a=0, int w=0, int ws=0, int pow=0) : CAnimal(strName, a, w), CHorse(pow, strName, a, w), CBird(ws, strName, a, w) { cout << "Pegasus constructor" << endl; } void Talk() { CBird::Talk(); } void Show() { CBird::Show(); CHorse::Show(); } ~CPegasus() { cout << "Pegasus destructor" << endl; } };int main() { //CBird birdObj(2, "Eagle", 5, 50); //CHorse horObj(10000, "Mogolia horse", 5, 1000); //CBull bullObj(20000, "Africa ox", 3, 2000); CPegasus pegObj("Pegasus", 5, 5000, 4, 100000); pegObj.Talk(); //会发出声音的 return 0; }