• C++ 类和对象 (5) 析构函数


            用构造函数创建对象后,程序负责跟踪该对象,直到对象过期为止。对象过期时,程序将自动调用一个特殊的成员函数,该函数的名称——析构函数。

            析构函数完成清理工作,实际上还是很有用的。

            例如,用new来分配一个构造函数,则析构函数将使用delete来释放这些内存。Stock的构造函数没有使用new,因此析构函数实际上没有需要它清除的工作。在此情况下,只需要让编译器生成一个什么都不做的隐式析构函数即可,Stock类第一版正是这样做的。

            举例,为Stock类提供一个析构函数。

            和构造函数一样,析构函数的名称也很特殊:在类名前加上~。因此,Stock类的析构函数为~Stock()。另外,和构造函数一样,析构函数也可以没有返回值和声明类型。与构造函数不同的是,析构函数没有参数,因此Stock析构函数的原型必须是:

    ~Stock();

            由于Stock的析构函数不承担任何重要的工作,因此可以将它编写为不执行任何操作的函数:

    1. Stock::~Stock()
    2. {
    3. }

            但是,有时候为了能看出析构函数何时被调用,可以这样写代码:

    1. Stock::~Stock()
    2. {
    3. cout << "ByeBye," << company <<"!"<
    4. }

            什么时候调用析构函数由编译器决定,通常不能再代码中显式地调用析构函数。如果

    1. 创建的是静态存储类对象,则其析构函数将在程序结束时自动被调用。
    2. 创建的是自动存储类对象,则其析构函数将在程序执行完代码块时自动被调用。

            如果对象是通过new创建的,则它将驻留在栈内存或者自由存储区中,当使用delete来释放内存时,其析构函数将自动被调用。最后,程序可以创建临时对象来完成特定的操作,在这种情况下,程序将在结束对该对象使用时自动调用其析构函数。

            由于在类对象过期时析构函数将自动被调用,因此必须有一个析构函数。如果程序员没有提供析构函数,编译器将隐式地声明一个默认析构函数,并在发现导致对象被删除的代码后,提供默认析构函数的定义。

            改进Stock类

            下面将对构造函数和析构函数加入到类和方法的定义中。

    1.头文件stock20.h,将构造函数和析构函数的原型加入到原来的类声明中。使用#ifndef防止多重包含。

    1. #ifndef __STOCK20_H__
    2. #define __STOCK20_H__
    3. #include
    4. class Stock
    5. {
    6. private:
    7. std::string company;
    8. long shares;
    9. double share_val;
    10. double total_val;
    11. void set_tot(){total_val = shares * share_val;}
    12. public:
    13. Stock();
    14. Stock(const std::string &co,long n,double pr);
    15. ~Stock();
    16. void buy(long num,double price);
    17. void sell(long num,double price);
    18. void update(double price);
    19. void show();
    20. };
    21. #endif

    2.实现文件stock20.cpp使用了using声明和限定名称来访问头文件中的各种声明,将构造函数和析构函数的方法定义添加到以前的方法中。并且每次被调用时,都显式一条信息。

    1. #include
    2. #include "stock20.h"
    3. Stock::Stock()
    4. {
    5. std::cout<<"Default constructor called\n";
    6. company = "no name";
    7. shares = 0;
    8. share_val = 0.0;
    9. total_val = 0.0;
    10. }
    11. Stock::Stock(const std::string &co,long n,double pr)
    12. {
    13. std::cout<<"Constructor using"<"called\n";
    14. company = co;
    15. if(n<0)
    16. {
    17. std::cout<<"Constructor using "<"called\n"
    18. <"shares set to 0.\n";
    19. shares = 0;
    20. }
    21. else
    22. shares = n;
    23. share_val = pr;
    24. set_tot();
    25. }
    26. Stock::~Stock()
    27. {
    28. std::cout<<"Bye,"<"!"<
    29. }
    30. void Stock::buy(long num,double price)
    31. {
    32. if(num<0)
    33. {
    34. std::cout<<"Numer of shares can't be negative,Transaction is aborted"
    35. <
    36. }
    37. else
    38. {
    39. shares += num;
    40. share_val = price;
    41. set_tot();
    42. }
    43. }
    44. void Stock::sell(long num,double price)
    45. {
    46. if(num<0)
    47. {
    48. std::cout<<"Numer of shares can't be negative,Transaction is aborted"
    49. <
    50. }
    51. else if(num >shares)
    52. {
    53. std::cout<<"You can't sell more than you have!Trancsaction is aborted"
    54. <
    55. }
    56. else
    57. {
    58. shares -= num;
    59. share_val=price;
    60. set_tot();
    61. }
    62. }
    63. void Stock::update(double price)
    64. {
    65. share_val = price;
    66. set_tot();
    67. }
    68. void Stock::show() const
    69. {
    70. std::cout<<"Company:"<
    71. std::cout<<"Shares:"<
    72. std::cout<<"Share price"<
    73. std::cout<<"Total worth:"<
    74. }

    3.客户文件,使用Stock类,显示了构造函数和析构函数。

    1. #include
    2. #include "stock20.h"
    3. int main()
    4. {
    5. {
    6. using std::cout;
    7. cout<<"Using constructors to create new objects\n";
    8. Stock stcok1("NanoSmart",12,20.0);
    9. stock1.show();
    10. Stock stock2=stock("Boffo objects",2,2.0);
    11. stock2.show();
    12. cout<<"Assingning stock1 to stock2:\n";
    13. stock2=stock1;
    14. cout<<"Listing stock1 and stock2:\n";
    15. stock1.show();
    16. stock2.show();
    17. cout<<"Using a constructor to reset an object\n";
    18. stock1=Stock("Nifty Foods",10,50.0);
    19. cout<<"Revised stock1:\n";
    20. stock1.show();
    21. cout<<"Done\n";
    22. const Stock land = Stock("Klu proper",3,3.0);
    23. land.show();
    24. }
    25. return 0;
    26. }

            值得注意的是,main()的开头和末尾多了一个大括号。

            诸如stock1和stock2等自动变量将在程序退出其定义所属代码块时消失。

            如果没有这些大括号,代码块将为整个main(),因此只有main()执行完毕后,才会调用析构函数。在窗口环境中,这意味着将在析构函数调用前关闭,导致无法看到信息。但是添加大括号后,析构函数调用将在到达返回语句前执行,从而显式相应信息。

  • 相关阅读:
    CatBoost算法模型实现贷款违约预测
    【vue3】08. 跟着官网学习vue3-列表渲染
    这几个小妙招让你学会如何压缩图片大小
    Redis之主从复制(一主两从)&薪火相传&反客为主&哨兵模式
    安装显卡驱动报错
    超低延时 TCP/UDP IP核
    rsync远程同步
    从0到1学会Git(第三部分):Git的远程仓库链接与操作
    Android 10.0 wifi的随机mac地址修改为固定不变
    Config
  • 原文地址:https://blog.csdn.net/m0_73671341/article/details/133394704