• C++零碎记录(十四)


    24. 纯虚函数抽象类

    ① 在多态中,通常父类中虚函数的实现时毫无意义的,主要都是调用子类重写的内容。因此,可以将虚函数改为纯虚函数。

    纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0;

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

    ④ 抽象类特点:

    1. 无法实例化对象
    2. 子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
    1. #include <iostream>
    2. using namespace std;
    3. //纯虚函数和抽象类
    4. class Base
    5. {
    6. public:
    7. //纯虚函数
    8. //只要有一个纯虚函数,这个类称为抽象类
    9. //抽象类特点:
    10. //1、无法实例化对象
    11. //2、抽象类的子类 必须要重写父类中的纯虚函数,否则也属于抽象类
    12. virtual void func() = 0;
    13. };
    14. class Son : public Base
    15. {
    16. public:
    17. virtual void func()
    18. {
    19. cout << "func函数调用" << endl;
    20. }
    21. };
    22. void test01()
    23. {
    24. //Base b; //抽象类是无法实例化对象
    25. //new Base; //抽象类是无法实例化对象
    26. //Son s; //子类中必须重写父类中的纯虚函数,否则无法实例化对象
    27. Base* base = new Son;
    28. base->func();
    29. }
    30. int main()
    31. {
    32. test01();
    33. system("pause");
    34. return 0;
    35. }

    运行结果:

    • func函数调用
    • 请按任意键继续. . .

    25. 虚析构和纯虚析构

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

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

    ③ 虚析构和纯虚析构共性:

    1. 可以解决父类指针释放子类对象
    2. 都需要有具体的函数实现

    ④ 虚析构语法:virtual.类名(){}

    ⑤ 纯虚析构语法:

    1. virtual~类名 = 0;
    2. 类名::~类名(){}

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

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

    ⑨ 拥有纯虚析构函数的类也属于抽象类。

    1. #include <iostream>
    2. using namespace std;
    3. #include<string>
    4. //纯虚函数和纯虚机构
    5. class Animal
    6. {
    7. public:
    8. Animal()
    9. {
    10. cout << "Animal构造函数调用" << endl;
    11. }
    12. //纯虚函数
    13. virtual void speak() = 0;
    14. /*
    15. //利用虚析构可以解决,父类指针释放子类对象时不干净的问题
    16. virtual ~Animal()
    17. {
    18. cout << "Animal析构函数调用" << endl;
    19. }
    20. */
    21. //纯虚析构 需要声明也需要实现
    22. //有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
    23. virtual ~Animal() = 0;
    24. };
    25. Animal::~Animal()
    26. {
    27. cout << "Animal纯虚析构函数调用" << endl;
    28. }
    29. class Cat : public Animal
    30. {
    31. public:
    32. Cat(string name)
    33. {
    34. cout << "Cat构造函数调用" << endl;
    35. m_Name = new string(name);
    36. }
    37. virtual void speak()
    38. {
    39. cout << *m_Name << "小猫在说话" << endl;
    40. }
    41. ~Cat()
    42. {
    43. if (m_Name != NULL)
    44. {
    45. cout << "Cat析构函数调用" << endl;
    46. delete m_Name;
    47. m_Name = NULL;
    48. }
    49. }
    50. string* m_Name;
    51. };
    52. void test01()
    53. {
    54. Animal* animal = new Cat("Tom");
    55. animal->speak();
    56. //父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露
    57. delete animal;
    58. }
    59. int main()
    60. {
    61. test01();
    62. system("pause");
    63. return 0;
    64. }

    运行结果:

    • Animal构造函数调用
    • Cat构造函数调用
    • Tom小猫在说话
    • Cat析构函数调用
    • Animal纯虚析构函数调用
    • 请按任意键继续. . .

    [ 完 ]
    链接:https://www.zhihu.com/question/437657370/answer/1692846096

  • 相关阅读:
    网页设计期末作业 使用HTML实现一个静态页面(含源码)
    微信小程序查询接口
    创新能力|如何用8D能力模型来提升产品经理的核心能力
    LC-992. K 个不同整数的子数组(滑动窗口)
    Linux上文本处理三剑客之sed
    PWA的特性、Service Worker的生命周期、拦截及缓存实例
    【学懂数据结构】数据结构绪论
    TMS Logging提供了短日志输出
    nginx七层负载均衡配置
    easypoi多级表头、多个sheet导出,动态导出列
  • 原文地址:https://blog.csdn.net/qq18218628646/article/details/132845575