• 【C++】多态 ③ ( “ 多态 “ 实现需要满足的三个条件 | “ 多态 “ 的应用场景 | “ 多态 “ 的思想 | “ 多态 “ 代码示例 )






    一、" 多态 " 实现条件




    1、" 多态 " 实现需要满足的三个条件


    " 多态 " 实现需要满足以下三个条件 :

    • 首先 , 要有继承关系 ;
    • 然后 , 父类中的函数需要有 virtual 关键字修饰 , 子类重写该 " 虚函数 " ;
    • 最后 , 父类指针 或 父类引用 指向 子类的对象 ;

    满足 ① 继承 , ② 虚函数重写 , ③ 父类指针/引用指向子类对象 三个条件 , 即可实现多态 ;


    在 C 语言中 , 指针存在的 最大意义 就是 " 间接赋值 " ;

    " 间接赋值 " 成立的三大条件 :

    • 首先 , 需要有两个变量 , 一个形参 , 一个实参 ;
      • 形参 是 函数 的 参数 , 指针 数据类型 ;
      • 实参 是 实际传入函数的 指针地址 ;
    • 然后 , 建立关系 , 将 实参 传递给 形参 ;
    • 最后 , 使用 传入的 指针 修改 实参的值 ;
      • 实际上修改的事 指针指向的地址 的内存数据 ;

    2、" 多态 " 的应用场景


    借助 " 多态 " , 我们可以事先 开发出 一套 软件框架 , 实现一些功能 ;

    在 软件框架 中 的 函数 中 , 传入 父类指针 作为 参数 , 之后 通过该 父类指针 调用其 virtual 虚函数 ;

    在之后的开发中 , 编写 子类 实现 父类 , 并 重写 父类的 virtual 虚函数 ;

    然后 调用 软件框架 中的 函数 , 传入 新编写 的 子类对象指针 , 此时 调用的 不再是 父类的 函数 , 而是 子类重写的 函数 ;

    这就实现了 复用 后面写的代码 ;


    3、" 多态 " 的思想


    " 封装 " 突破了 C 语言 的 函数概念 , C 语言中的 函数 仅能 封装 逻辑操作 , " 封装 " 能将 数据 和 操作 同时封装到一起 , 组成类 ;

    将 封装好的 类对象 传入函数中 , 可以在函数中调用 类对象的 成员变量 和 成员方法 ;

    • 如果仅 传入 C 语言 的函数 , 仅能调用 函数 中的逻辑代码 ;
    • 如果仅 传入 数据 , 操作该数据的逻辑代码需要额外传入 ;

    " 继承 " 可以实现 代码的 复用 , 这里的 复用 是 复用 之前写的代码 ;


    " 多态 " 实现的也是 代码 的复用 , 这里的 复用 是 复用 之后写的代码 ;

    " 多态 " 多用于 软件框架 , 提前实现 功能框架 , 功能细节 , 使用多态在后续开发时实现 ;





    二、" 多态 " 代码示例



    先开发出 导弹发射 的框架出来 , 此时还没有研究出导弹 , missileFire 函数用于发射导弹 ;

    void missileFire(Missile* missile)
    {
    	// 发射导弹
    	missile->fire();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    后期 , 研究出了 DF1 导弹 , 为其设置发射方法 , 重写 发射 虚函数 , 此时向 missileFire 函数中传入 DF_1 类的对象地址 , 调用的事 DF_1 类对象的发射方法 ;

    	DF_1 df1;
    	missileFire(&df1);
    
    • 1
    • 2

    研究出了 DF2 导弹 , 为其设置发射方法 , 重写 发射 虚函数 , 此时向 missileFire 函数中传入 DF_2 类的对象地址 , 调用的事 DF_2 类对象的发射方法 ;

    	DF_2 df2;
    	missileFire(&df2);
    
    • 1
    • 2

    研究出了 DF3 导弹 , 为其设置发射方法 , 重写 发射 虚函数 , 此时向 missileFire 函数中传入 DF_3 类的对象地址 , 调用的事 DF_3 类对象的发射方法 ;

    	DF_3 df3;
    	missileFire(&df3);
    
    • 1
    • 2

    注意 : 要 多态 的函数 , 必须使用 virtual 关键字 , 将其设置为虚函数 ;


    代码示例 :

    #include "iostream"
    using namespace std;
    
    // 父类 - 导弹
    class Missile {
    public:
    	virtual void fire()
    	{
    		cout << "发射导弹" << endl;
    	}
    public:
    	int scope;
    };
    
    class DF_1 : public Missile
    {
    public:
    	virtual void fire()
    	{
    		cout << "发射东风1导弹, 射程 " << scope << " 公里" << endl;
    	}
    public:
    	int scope = 600;
    };
    
    class DF_2 : public Missile
    {
    public:
    	virtual void fire()
    	{
    		cout << "发射东风2导弹, 射程 " << scope << " 公里" << endl;
    	}
    public:
    	int scope = 1300;
    };
    
    class DF_3 : public Missile
    {
    public:
    	virtual void fire()
    	{
    		cout << "发射东风3导弹, 射程 " << scope << " 公里" << endl;
    	}
    public:
    	int scope = 2800;
    };
    
    void missileFire(Missile* missile)
    {
    	// 发射导弹
    	missile->fire();
    }
    
    
    int main() {
    
    	DF_1 df1;
    	missileFire(&df1);
    
    	DF_2 df2;
    	missileFire(&df2);
    
    	DF_3 df3;
    	missileFire(&df3);
    	
    	
    	// 控制台暂停 , 按任意键继续向后执行
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    执行结果 :

    发射东风1导弹, 射程 600 公里
    发射东风2导弹, 射程 1300 公里
    发射东风3导弹, 射程 2800 公里
    请按任意键继续. . .
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

  • 相关阅读:
    【POST请求-腾讯翻译君-爬虫案例】
    Python(12)进程与线程
    golang map 初始化 和 使用
    速览 ETHGlobal Async 黑客松决赛项目:DAO 治理隐私保护趋势涌现
    基于Springboot的宠物医院管理系统-JAVA【数据库设计、论文、源码、开题报告】
    删除docker容器日志
    tableau 处理MySql 的bug:时间列被自动加上一个月
    智能电力仪表采集在某厂房二期电力监控系统的设计和应用
    Spring源码深度解析(六):Spring事务原理详解
    Linux 驱动扫描所有线程调用栈
  • 原文地址:https://blog.csdn.net/han1202012/article/details/134084322