C++类和对象-多态->多态的基本语法、多态的原理剖析、纯虚函数和抽象类、虚析构和纯虚析构

#include<iostream>
using namespace std;

//多态
//动物类
class Animal
{
public:
    //Speak函数就是虚函数
    //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};
//猫类
class Cat :public Animal
{
public:
    //重写 函数返回值类型  函数名  参数列表  完全相同
    void speak()
    {
        cout << "小猫在说话" << endl;
    }
};
//狗类
class Dog :public Animal
{
public:

    void speak()
    {
        cout << "小狗在说话" << endl;
    }

};
//我们希望传入什么对象,那么就调用什么对象的函数
//如果函数地址在编译阶段就能确定,那么静态联编
//如果函数地址在运行阶段才能确定,就是动态联编

//执行说话的函数
//地址早绑定  在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定

//动态多态满足条件
//1.有继承关系
//2.子类重写父类的虚函数

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

void DoSpeak(Animal & animal)
{
    animal.speak();
}
//
//多态满足条件:
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象

void test01()
{
    Cat cat;
    DoSpeak(cat);


    Dog dog;
    DoSpeak(dog);
}


int main() {

    test01();

    system("pause");

    return 0;
}

总结:

多态满足条件

* 有继承关系
* 子类重写父类中的虚函数

多态使用条件

* 父类指针或引用指向子类对象

重写:函数返回值类型  函数名 参数列表 完全一致称为重写

#include<iostream>
using namespace std;

//纯虚函数和抽象类
class Base
{
public:
    //纯虚函数
    //类中只要有一个纯虚函数就称为抽象类
    //抽象类特点:
    //1.无法实例化对象
    //2.抽象类的子类 必须重写父类中的纯虚函数,否则也属于抽象类
    virtual void func() = 0;
};

class Son :public Base
{
public:
    virtual void func()
    {
        cout << "func调用" << endl;
    };
};

void test01()
{
    //Base b;   //抽象类无法实例化对象
    //new Base; //抽象类无法实例化对象
    //Son s;//子类必须重写父类中的纯虚函数,否则无法实例化对象
    Base * base = new Son;
    base->func();
    delete base;//记得销毁
}

int main() {

    test01();

    system("pause");

    return 0;
}

#include<iostream>
using namespace std;
#include<string>

//虚析构和纯虚析构
class Animal
{
public:

    Animal()
    {
        cout << "Animal 构造函数调用!" << endl;
    }
    //纯虚函数
    virtual void Speak() = 0;

    //利用虚析构可以解决 父类指针释放子类对象时不干净的问题
    //析构函数加上virtual关键字,变成虚析构函数
    //virtual ~Animal()
    //{
    //    cout << "Animal虚析构函数调用!" << endl;
    //}

    //纯虚析构  需要声明也需要实现
    //有了纯虚析构 之后,这个类也属于抽象类,无法实例化对象
    virtual ~Animal() = 0;
};

Animal::~Animal()
{
    cout << "Animal 纯虚析构函数调用!" << endl;
}

//和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。

class Cat : public Animal
{
public:
    Cat(string name)
    {
        cout << "Cat构造函数调用!" << endl;
        m_Name = new string(name);
    }
    virtual void Speak()
    {
        cout << *m_Name <<  "小猫在说话!" << endl;
    }
    ~Cat()
    {
        cout << "Cat析构函数调用!" << endl;
        if (this->m_Name != NULL)
        {
            delete m_Name;
            m_Name = NULL;
        }
    }

public:
    string * m_Name;
};

void test01()
{
    Animal * animal = new Cat("Tom");
    animal->Speak();

    //通过父类指针去释放,会导致子类对象可能清理不干净,造成内存泄漏
    //怎么解决?给基类增加一个虚析构函数
    //虚析构函数就是用来解决通过父类指针释放子类对象

    //父类指针在析构时候 不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露
    delete animal;
}

int main() {

    test01();

    system("pause");

    return 0;
}

总结:

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/470681.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++文件操作->文本文件(->写文件、读文件)、二进制文件(->写文件、读文件)

#include<iostream> using namespace std; #include <fstream>//头文件包含 //文本文件 写文件 void test01() { //1.包含头文件 fstream //2.创建流对象 ofstream ofs; //3.指定打开方式 ofs.open("test.txt", ios::out); //4.写…

将人工智能应用于 DNS 流量以阻止恶意软件感染

Infoblox Inc. 透露&#xff0c;它正在利用人工智能 (AI) 来识别恶意软件来源的网站。然后可以阻止这些网站以使 IT 环境更加安全。 Infoblox 产品管理副总裁 Craig Sanderson 桑德森表示&#xff0c;SOC Insights 将机器学习算法应用于 BloxOne 威胁防御平台域名服务器 (DNS)…

[职场] 生育津贴如何申领与计算 #经验分享#微信#职场发展

生育津贴如何申领与计算 生育津贴如何申领? 生育津贴即为产假工资&#xff0c;相当于女职工在享受符合生育政策休假期间的工资。生育津贴高于本人产假工资标准的&#xff0c;用人单位不得克扣生育津贴低于本人产假工资标准的&#xff0c;差额部分由用人单位补足。 一、大部…

ArcgisForJS基础

文章目录 0.引言1.第一个ArcgisForJS应用程序1.1.安装部署ArcgisForJS1.2.实现ArcgisForJS应用程序 2.开发与调试工具2.1.集成开发环境2.2.调试工具2.3.Firebug 0.引言 ArcGIS API for JavaScript是一款由Esri公司开发的用于创建WebGIS应用的JavaScript库。它允许开发者通过调…

Vi 和 Vim 编辑器

Vi 和 Vim 编辑器 vi 和 vim 的基本介绍 Linux 系统会内置 vi 文本编辑器 Vim 具有程序编辑的能力&#xff0c;可以看做是 Vi 的增强版本&#xff0c;可以主动的以字体颜色辨别语法的正确性&#xff0c;方便程序设计。 代码补完、编译及错误跳转等方便编程的功能特别丰富&…

探索设计模式的魅力:创建型设计模式的比较与决策

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 一、设计模式概览 1.1 创建型模式 二、比较创建型设计模式 1.1 适用场景典型用例 1.2 关键要素与差异对比 1.3 结构图 三、模式选择指南 3.1 场景分析 3.2 决策流程图 四、结语 4.1 优势 4.2 考量因素 一、…

MySQL 基础知识(六)之数据查询(二)

目录 6 数值型函数 7 字符串函数 8 流程控制函数 9 聚合函数 10 分组查询 (group by) 11 分组过滤 (having) 12 限定查询 (limit) 13 多表查询 13.1 连接条件关键词 (on、using) 13.2 连接算法 13.3 交叉连接 (cross join) 13.4 内连接 (inner join) 13.5 外连接 …

装饰工程|装饰工程管理系统-项目立项子系统的设计与实现|基于Springboot的装饰工程管理系统设计与实现(源码+数据库+文档)

装饰工程管理系统-项目立项子系统目录 目录 基于Springboot的装饰工程管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;2&#xff09;合同报价管理 &#xff08;3&#xff09;装饰材料总计划管理 &#xff08;4&#xff0…

边缘计算:重塑数字世界的未来

引言 随着物联网&#xff08;IoT&#xff09;设备的激增和5G网络的普及&#xff0c;我们正站在一个计算模式的新纪元门槛上——边缘计算。这一技术范式将数据处理和分析推向网络的边缘&#xff0c;即设备或终端&#xff0c;为实时性要求较高的应用提供了前所未有的可能性。 目…

Unity如何修改预制体(预制件)?

文章目录 19 复制复制复制&#xff0c;预制体与变体 19 复制复制复制&#xff0c;预制体与变体 【预制件】 预制件作用&#xff1a;方便复用 【预制件】的制作 直接拖拽&#xff0c;从层级面板 -> 项目面板。层级面板中当前图标会变蓝&#xff0c;子物体名字变蓝色。预制件…

【JavaEE】_文件与IO

目录 1.文件概述 1.1 文件的概念 1.2 文件的存储 1.3 文件的分类 1.4 目录结构 1.5 文件操作 1.5.1 文件系统操作 1.5.2 文件内容操作 2. Java文件系统操作 2.1 File类所处的包 2.2 构造方法 2.3 方法 2.3.1 与文件路径、文件名有关的方法 2.3.2 文件是否存在与普…

【Visual Studio】使用空格替换制表符

环境 VS版本&#xff1a;VS2013 问题 如何生成空格替换制表符&#xff1f; 步骤 1、菜单 工具->选项&#xff0c;文本编辑器->C/C->制表符&#xff0c;选择【插入空格】。