• <C++>多态的实战,详解三个具体案例


    历尽岁月沧桑,也愿你始终相信人间值得

    ✨写在前面

            书接上文,今天就以三个案例来把C++多态的内容结束。第一个案例就是用多态写一个计算器并实现简单的加减乘除操作;第二个案例就是一个饮品制作,主要就是抽象类重写方法;第三个是比较综合的电脑组装案例,正文会详细介绍;那么就开始上手操作吧!

           ✨✨ 感兴趣的同学可以订阅一下我的这个《C++入门》专栏喔~✨✨


    ✨目录

    案例一:计算器

    案例要求

    代码实现

    代码解释 

    运行效果

    案例二:制作饮品

    案例要求

    代码实现

    代码解释

    运行效果 

    案例三:电脑组装

    案例要求

    代码实现

    代码解释

    运行效果

    ✨总结 


    案例一:计算器

    案例要求

            使用多态实现计算器的加减乘除操作

    代码实现

    1. class AbstractCalculator
    2. {
    3. public:
    4. //纯虚函数,用来得到计算结果
    5. virtual void getResult() = 0;
    6. float num1, num2;
    7. };
    8. //加法类
    9. class Add :public AbstractCalculator
    10. {
    11. public:
    12. void getResult()
    13. {
    14. cout << num1 << "+" << num2 << "=" << num1 + num2 << endl;
    15. }
    16. };
    17. //减法类
    18. class Sub :public AbstractCalculator
    19. {
    20. public:
    21. void getResult()
    22. {
    23. cout << num1 << "-" << num2 << "=" << num1 - num2 << endl;
    24. }
    25. };
    26. //乘法类
    27. class Mul :public AbstractCalculator
    28. {
    29. public:
    30. void getResult()
    31. {
    32. cout << num1 << "*" << num2 << "=" << num1 * num2 << endl;
    33. }
    34. };
    35. //除法类
    36. class Des :public AbstractCalculator
    37. {
    38. public:
    39. void getResult()
    40. {
    41. cout << num1 << "/" << num2 << "=" << num1 / num2 << endl;
    42. }
    43. };
    44. void main()
    45. {
    46. //1、加法
    47. AbstractCalculator *abc = new Add();
    48. abc->num1 = 2.1;
    49. abc->num2 = 3.9;
    50. abc->getResult();
    51. delete abc;
    52. //2、减法
    53. abc = new Sub();
    54. abc->num1 = 3.9;
    55. abc->num2 = 2.1;
    56. abc->getResult();
    57. delete abc;
    58. //3、乘法
    59. abc = new Mul();
    60. abc->num1 = 4.2;
    61. abc->num2 = 2;
    62. abc->getResult();
    63. delete abc;
    64. //4、除法
    65. abc = new Des();
    66. abc->num1 = 8.8;
    67. abc->num2 = 2;
    68. abc->getResult();
    69. delete abc;
    70. }

    代码解释 

            首先创建AbstractCalculator类作为基类,设置两个浮点型属性用来做基本运算,并含有纯虚函数getResult。我们知道还有纯虚函数的类被称为抽象类,特点是无法实例化,非抽象子类必须重写抽象类的所有纯虚函数,因此基本运算的类都要重写getResult方法。接下来写了加减乘除四个派生类继承该抽象类,分别给派生类的getResult进行重写,得到不同的计算结果。主函数中利用父类指针来创建子类对象,给两个操作数赋值后调用getResult方法,然后利用delete删除指针。注意删除指针只是删除了那一块地址,该指针的类型是不变的,还可以多次利用,指向不同的子类对象。

    运行效果


    案例二:制作饮品

    案例要求

            给出制作饮品的过程为四步:把水煮开、冲泡、倒入杯中、加入佐料。

            利用多态写出两个饮品的制作过程

    代码实现

    1. #include<iostream>
    2. using namespace std;
    3. //使用多态制作奶茶
    4. class AbstractDrink
    5. {
    6. public:
    7. //制作开水
    8. virtual void boiledWater() = 0;
    9. //冲泡
    10. virtual void brew() = 0;
    11. //倒入杯中
    12. virtual void inCup() = 0;
    13. //加入佐料
    14. virtual void pour() = 0;
    15. void makeDrink()
    16. {
    17. this->boiledWater();
    18. this->brew();
    19. this->inCup();
    20. this->pour();
    21. }
    22. };
    23. //制作咖啡
    24. class Coffee :public AbstractDrink
    25. {
    26. public:
    27. //煮水
    28. virtual void boiledWater()
    29. {
    30. cout << "先把水煮开" << endl;
    31. }
    32. //冲泡
    33. virtual void brew()
    34. {
    35. cout << "开始冲泡咖啡" << endl;
    36. }
    37. //倒入杯中
    38. virtual void inCup()
    39. {
    40. cout << "全部倒入杯中" << endl;
    41. }
    42. //加入辅料
    43. virtual void pour()
    44. {
    45. cout << "加入糖和牛奶" << endl;
    46. cout << "牛奶咖啡制作完成" << endl;
    47. }
    48. };
    49. //制作茶水
    50. class Tea :public AbstractDrink
    51. {
    52. public:
    53. //煮水
    54. virtual void boiledWater()
    55. {
    56. cout << "先把水煮开" << endl;
    57. }
    58. //冲泡
    59. virtual void brew()
    60. {
    61. cout << "开始冲泡茶叶" << endl;
    62. }
    63. //倒入杯中
    64. virtual void inCup()
    65. {
    66. cout << "全部倒入杯中" << endl;
    67. }
    68. //加入辅料
    69. virtual void pour()
    70. {
    71. cout << "加入枸杞" << endl;
    72. cout << "茶水制作完成" << endl;
    73. }
    74. };
    75. //制作函数
    76. void DoWork(AbstractDrink* abs)//父类指针指向子类对象AbstractDrinking* abs = new Coffee;
    77. {
    78. abs->makeDrink();
    79. delete abs;//手动释放
    80. //堆区的数据被销毁了但是指针的类型没变,可以多次利用
    81. }
    82. void test()
    83. {
    84. DoWork(new Coffee);
    85. cout << "---------------------" << endl;
    86. DoWork(new Tea);
    87. }
    88. void main()
    89. {
    90. test();
    91. }

    代码解释

            这个案例就是直接给一个类中加四个纯虚函数,然后再加一个makeDrink方法来调用全部函数。子类中需要重写四个纯虚函数,制作咖啡和茶的类步骤基本一样。在DoWork函数的形参列表,使用父类的指针,那么在test函数调用DoWork函数就可以直接new子类对象,这样也是父类指针指向子类对象,然后调用makeDrink方法后,用delete删除堆区父类指针,以免内存泄漏。

    运行效果 


    案例三:电脑组装

    案例要求

    电脑主要组成部件为 CPU(用于计算),显卡(用于显示),内存条(用于存储)

    将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Intel厂商和Lenovo厂商

    创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口

    测试时组装三台不同的电脑进行工作

    代码实现

    1. class CPU
    2. {
    3. public:
    4. virtual void calculate() = 0;
    5. };
    6. class VideoCard
    7. {
    8. public:
    9. virtual void display() = 0;
    10. };
    11. class Storage
    12. {
    13. public:
    14. virtual void storage() = 0;
    15. };
    16. class Computer
    17. {
    18. public:
    19. Computer(CPU* cpu, VideoCard* vc, Storage* sto)
    20. {
    21. m_cpu = cpu;
    22. m_vc = vc;
    23. m_sto = sto;
    24. }
    25. //提供一个工作的函数
    26. void work()
    27. {
    28. m_cpu->calculate();
    29. m_vc->display();
    30. m_sto->storage();
    31. }
    32. //提供析构函数释放3个电脑零件
    33. ~Computer()
    34. {
    35. //释放CPU零件
    36. if (m_cpu != NULL)
    37. {
    38. delete m_cpu;
    39. m_cpu = NULL;
    40. }
    41. //释放显卡零件
    42. if (m_vc != NULL)
    43. {
    44. delete m_vc;
    45. m_vc = NULL;
    46. }
    47. //释放内存条零件指针
    48. if (m_sto != NULL)
    49. {
    50. delete m_sto;
    51. m_sto = NULL;
    52. }
    53. }
    54. private:
    55. CPU* m_cpu;//CPU零件指针
    56. VideoCard* m_vc;//显卡零件指针
    57. Storage* m_sto;//内存条零件指针
    58. };
    59. //Intel
    60. class IntelCPU :public CPU
    61. {
    62. public:
    63. virtual void calculate()
    64. {
    65. cout << "Intel的CPU开始计算了" << endl;
    66. }
    67. };
    68. class IntelVideoCard :public VideoCard
    69. {
    70. public:
    71. virtual void display()
    72. {
    73. cout << "Intel的显卡开始显示了" << endl;
    74. }
    75. };
    76. class IntelMemory :public Storage
    77. {
    78. public:
    79. virtual void storage()
    80. {
    81. cout << "Intel的内存条开始存储了" << endl;
    82. }
    83. };
    84. //Lenovo
    85. class LenovoCPU :public CPU
    86. {
    87. public:
    88. virtual void calculate()
    89. {
    90. cout << "Lenovo的CPU开始计算了" << endl;
    91. }
    92. };
    93. class LenovoVideoCard :public VideoCard
    94. {
    95. public:
    96. virtual void display()
    97. {
    98. cout << "Lenovo的显卡开始显示了" << endl;
    99. }
    100. };
    101. class LenovoMemory :public Storage
    102. {
    103. public:
    104. virtual void storage()
    105. {
    106. cout << "Lenovo的内存条开始存储了" << endl;
    107. }
    108. };
    109. //组装电脑
    110. void test01()
    111. {
    112. //创建第一台电脑
    113. Computer* c1 = new Computer(new IntelCPU,new IntelVideoCard, new IntelMemory);
    114. c1->work();
    115. delete c1;
    116. cout << "***********************" << endl;
    117. //组装第二台电脑
    118. Computer* c2 = new Computer(new LenovoCPU, new LenovoVideoCard, new LenovoMemory);
    119. c2->work();
    120. delete c2;
    121. cout << "***********************" << endl;
    122. //组装第三台电脑
    123. Computer* c3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory);
    124. c3->work();
    125. delete c3;
    126. }
    127. void main()
    128. {
    129. test01();
    130. system("pause");
    131. }

    代码解释

            首先把CPU,显卡,内存条做成基类并各自添加纯虚函数,强制派生类进行重写。

    然后创建Computer类,封装三个零件类的指针,在电脑类的有参构造中传入三个零件的指针并赋值,提供work函数调用各个零件的功能函数。在程序结束之前编译器会自动调用析构,所以我提供一个电脑类的析构函数,释放掉三个零件的指针。

            接下来提供两个品牌,有Intel和Lenovo两个品牌的三种零件。对每个品牌的三个零件类进行继承并重写功能函数,提示具体品牌的零件做了什么具体的功能。

            最后创建三个电脑,将零件进行组装,可以全部都是Intel也可以都是Lenovo也可以混合着组装。利用new开辟电脑类,直接使用有参构造,将new出来的零件类传给对应的父类指针,完成多态的使用。电脑类创建完毕后调用work函数使电脑运行,随后就将堆区指针删除,防止内存泄露。

    运行效果

    总结 

            在最后庆祝C++多态完美学习结束,学习完知识再完成练习的学习方法真的很赞,希望给大家带来了帮助,下篇博客不见不散!!!

  • 相关阅读:
    springMVC的学习【中】
    (附源码)springboot毕业生弃置物品交易系统 毕业设计 231151
    WEB前端网页设计 HTML CSS 网页设计参数 - 【高度坍塌】
    Docker安装Bitbucket
    java后端开发面试准备(1)-Redis缓存
    初步认识Java
    《Care Bears 爱心熊》人物化身来到 The Sandbox 元宇宙!
    Excel中截取特殊字符之前、之间、之后的数据
    【大连民族大学C语言CG题库练习题】——逆序乘积式
    CSS 笔记(十一):属性 —— 特效
  • 原文地址:https://blog.csdn.net/m0_58618795/article/details/125493384