2020-02-16 C++核心编程05-基本框架

4.6.7多继承语法

C++中允许一个类继承多个类

多继承可能会引发父类中有同名成员出现,需要加作用域区分

C++实际开发中不建议使用多继承


4.6.8菱形继承--虚继承

概念:两个派生类继承同一个基类,又有某个类同时继承这两个派生类,

这种继承称为菱形继承,或钻石继承;

虚继承:在继承之前加virtual关键字

虚基类:被虚继承的类称为虚基类

虚基类指针 vbptr (virtual base pointer) :虚继承基类的派生类的对象内存中会生成一个vbptr

指向 vbtable 虚基类表 :虚基类表中记录了指针到相同属性数据的偏移量,

通过偏移量找到数据,所以同一属性数据不需要重复存储.

示例:

class Animal

{

public:

int m_Age;

};

//利用虚继承 解决菱形继承问题

//在继承之前加关键字 virtual

//Animal类称为 虚基类

class Sheep:virtual public Animal{};

class Tuo:virtual public Animal{};

class SheepTuo:public Sheep, public Tuo{};

void test01()

{

SheepTuo st;

st.Sheep::m_Age = 18;

st.Tuo::m_Age = 28;

//当菱形继承,两个父类拥有相同的属性,需要加以作用域区分

cout << "st.Sheep::m_Age=" << st.Sheep::m_Age << endl;

cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;

//这份属性数据只需一份,菱形继承导致数据有两份,资源浪费

cout << "st.m_Age=" << st.m_Age << endl;

}

总结: 1.菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义

      2.利用虚继承可以解决菱形继承问题


4.7多态

4.7.1多态的基本概念

多态是C++面向对象三大特性之一

多态分为两类:

1.静态多态:函数重载和运算符重载属于静态多态,复用函数名;

2.动态多态:派生类和虚函数实现运行时多态;

区别:

1.静态多态的函数地址早绑定,编译阶段确定函数地址;

2.动态多态的函数地址晚绑定,运行阶段确定函数地址;

示例:

class Animal

{

public:

void speak1()

{

cout << "Animal::speak1()" << endl;

}

//虚函数

virtual void speak2()

{

cout << "Animal::speak2()" << endl;

}

};

class Cat

:public Animal

{

public:

void speak1()

{

cout << "Cat::speak1()" << endl;

}

//重写 函数返回值类型 函数名 参数列表 完全相同

void speak2()

{

cout << "Cat::speak2()" << endl;

}

};

void doSpeak(Animal &animal)

{

//地址早绑定 在编译阶段确定函数地址

    //如果想执行让猫说话,那么这个函数地址不能提前绑定

    //需要在运行阶段进行绑定,地址晚绑定,即实现动态多态

animal.speak1();

cout <<"-----------" << endl;

//函数地址不能提前确定

//需要看传入对象类型

animal.speak2();

//动态多态满足条件

//1.有继承关系

//2.子类要重写父类的虚函数

//动态多态使用

//父类的指针或引用指向子类对象

}

void test01()

{

Cat cat;

doSpeak(cat);//Animal &animal=cat;

}

总结:

动态多态满足条件

1.有继承关系

2.子类要重写父类的虚函数

动态多态使用:父类的指针或引用指向子类对象

重写 函数返回值类型 函数名 参数列表 完全相同


4.7.2多态案例1-计算器类

案例描述:

分别利用普通写法和多态技术,设计实现两个操作数进行计算的计算器类

多态优点:

1.代码组织结构清晰

2.可读性强

3.利于前期和后期和扩展以及维护


4.7.3纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容

因此可以将虚函数改为纯虚函数.

纯虚函数语法:

virtual 返回值类型 函数名 (参数列表)=0

当类中有了纯虚函数,这个类称为抽象类.

抽象类特点:

1.无法实例化对象;

2.子类必须重写抽象类中的纯虚函数,否则该子类也是抽象类;


4.7.4多态案例2-制作饮品

案例描述:

制作饮品大致流程为 煮水 冲泡 倒入杯中 加入辅料

利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶


4.7.5虚析构和纯虚析构

多态使用时,如果子类中属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:将父类中的析构函数改为虚析构或纯虚析构

虚析构和纯虚析构共性:

1.可以解决父类指针释放子类对象;

2.都需要有具体的函数实现;

虚析构和纯虚析构区别:

如果是纯虚析构,该类属于抽象类,无法实例化对象

总结:

1.虚析构或纯虚析构就是用来解决通过父类指针释放子类对象;

2.如果子类中没有堆区数据,可以不写为虚析构或纯虚析构;

3.拥有纯虚析构函数的类也属于抽象类;

你可能感兴趣的:(2020-02-16 C++核心编程05-基本框架)