注册 登录
编程论坛 C++教室

析构函数有一点不理解

lyl930130 发布于 2016-01-17 12:44, 2810 次点击
程序代码:
stock.c:
#include "stdafx.h"
#include "stock.h"
#include <iostream>

Stock::Stock()
{
    std::cout<<"Default constructor called\n";
    company="no name";
    shares=0;
    share_val=0.0;
    total_val=0.0;

}

Stock::Stock(const std::string &co,long n,double pr)
{
    std::cout <<"Constructor using"<<co<<"called\n";
    company=co;
    shares=n;
    share_val=pr;
    set_tot();

}

Stock::~Stock()
{
    std::cout<<"bye,"<<company<<"!\n";

}

void Stock::buy(long num,double price)
{
    shares+=num;
    share_val=price;
    set_tot();
}

void Stock::sell(long num,double price)
{
    shares-=num;
    share_val=price;
    set_tot();
}

void Stock::update(double price)
{
    share_val=price;
    set_tot();
}

void Stock::show()
{
    using std::cout;
    using std::ios_base;

    ios_base::fmtflags orig=cout.setf(ios_base::fixed,ios_base::floatfield);
    std::streamsize prec =cout.precision(3);
   
    cout<<"Company: "<<company
        <<" Shares: "<<shares<<'\n';
    cout<<" Share price:$"<<total_val<<'\n';
    cout.precision(2);
    cout<<" Total Worth:$"<<total_val<<'\n';
    cout.setf(orig,ios_base::floatfield);
    cout.precision(prec);
}

stock.h:
#ifndef STOCK_H
#define STOCK_H
#include <string>

class Stock
{
public:
    Stock();
    Stock(const std::string &co,long n=0,double pr=0.0);
    ~Stock();
    void buy(long num,double price);
    void sell(long num,double price);
    void update(double price);
    void show();

private:
    std::string company;
    long shares;
    double share_val;
    double total_val;
    void set_tot() {total_val=shares*share_val;}

};
#endif

main:
#include "stdafx.h"
#include <iostream>
#include "stock.h"
#include <stdio.h>

   
   
int main()
{
    {
        using std::cout;
        cout<<"Using constructors to create new objects\n";
        Stock stock1("Nanosmart",12,20.0);
        stock1.show();
        Stock stock2=Stock("Boffo Objects",2,2.0);
        stock2.show();

        cout<<"Assigning stock1 to stock2:\n";
        stock2=stock1;
        cout<<"Listing stock1 and stock2\n";
        stock1.show();
        stock2.show();

        cout<<"Using a constructor to reset an object\n";
        stock1=Stock("Nifty Foods",10,50.0);
        cout<<"Revised stock1\n";
        stock1.show();
        cout<<"Done\n";

    }
    return 0;
}


结果:
程序代码:
Using constructors to create new objects
Constructor usingNanosmartcalled
Company: Nanosmart Shares: 12

 Share price:$240.000

 Total Worth:$240.00
Constructor usingBoffo Objectscalled
Company: Boffo Objects Shares: 2

 Share price:$4.000

 Total Worth:$4.00
Assigning stock1 to stock2:
Listing stock1 and stock2
Company: Nanosmart Shares: 12

 Share price:$240.000

 Total Worth:$240.00
Company: Nanosmart Shares: 12

 Share price:$240.000

 Total Worth:$240.00
Using a constructor to reset an object
Constructor usingNifty Foodscalled
bye,Nifty Foods!
Revised stock1
Company: Nifty Foods Shares: 10

 Share price:$500.000

 Total Worth:$500.00
Done
bye,Nanosmart!
bye,Nifty Foods!
请按任意键继续. . .


1:sotck2=stock1 这里传递的是数组的值还是数组的地址
2:stock1=Stock("Nifty Foods"....)这一步为什么出现的是  Bye,Nifty Foods!   我理解应该是Bye,Nanosmart!
18 回复
#2
hjx11202016-01-17 17:02
问题1:可以参考C语言中的strcpy()和strncpy()函数
到底是数值还是数组地址可以在楼主的这本书的第四章找到答案
最简单的法子就是写个函数输出stock2和stock1的十六进制看看不就知道了

问题2:为什么会出现 Bye,XXX是因为析构函数Stock::~Stock()
具体代码:
程序代码:
Stock::~Stock()
{
    std::cout<<"bye,"<<company<<"!\n";

}

#3
yangfrancis2016-01-17 19:39
没看到重载=运算符的代码。stock2=stock1真能跑吗,表示怀疑
#4
lyl9301302016-01-17 22:52
回复 2楼 hjx1120
问题1自己看了下,传递的是值而不是地址。其实从Done之后的输出也可以看出来
问题2是我没表述清楚。我知道输出bye,***是析构函数,我的困惑在于之前stock1的值是Nanasmart,那么调用析构函数应该是bye,Nanosmart
之后再构造函数,stock1的值变成Nifty。如果这个时候再调用析构函数,才是输出bye,Nifty。
#5
lyl9301302016-01-17 22:55
回复 3楼 yangfrancis
对C++了解不多,代码是能跑的,我自己的换句是win7_64 vs2012,提问区第二段代码段就是输出结果
重载运算符=就不是特别清楚,我现在只能把它理解为何int a=b一样的赋值。
#6
TonyDeng2016-01-17 23:41
你想測試什麽呀?測試析構函數幹什麽?析構函數不是你想調用就能調用的,也不是你主動調用過之後它就不會再被調用的。
#7
wmf20142016-01-18 16:17
就我理解:
1,类对象之间的赋值应该是数据拷贝,如果是传地址则会出现影子类对象,修改一个另一个也会修改。
2,从main函数看,最后执行了“stock1=Stock("Nifty Foods",10,50.0);”语句,所以return前执行释放stock1的动作显示“Bye,Nifty Foods!”没有问题。
#8
TonyDeng2016-01-18 16:21
以下是引用wmf2014在2016-1-18 16:17:50的发言:

就我理解:
1,类对象之间的赋值应该是数据拷贝,如果是传地址则会出现影子类对象,修改一个另一个也会修改。
2,从main函数看,最后执行了“stock1=Stock("Nifty Foods",10,50.0);”语句,所以return前执行释放stock1的动作显示“Bye,Nifty Foods!”没有问题。

复製?既然是复製,那麽就存在兩個對象,爲什麽祇釋放了一個?樓主就問這個。
#9
wmf20142016-01-18 16:28
是两个啊,他提供的执行结果不是有两个bye吗?
.
.
.
bye,Nanosmart!
bye,Nifty Foods!
请按任意键继续. . .
#10
lyl9301302016-01-18 16:47
回复 9楼 wmf2014
T版正解。
现在搞明白了。出现第一个bye,Nifty Foods!是因为stock1=Stock("Nifty Foods",10,50.0)时,stock1已经有值了,现在再赋值就重新创建了一个临时的stock_temp,然后再将这个临时stock_temp的值赋值给stock1,赋值完之后这个临时的stock_temp就要消失了,所以这个时候临时的stcok_temp调用它的析构函数,所以会输出bye,Nifty Foods!
#11
TonyDeng2016-01-18 16:51
回复 9楼 wmf2014
他測試了直接初始化和賦値初始化兩種,對賦値初始化來説,除了被賦値的對象,還有賦値給人的對象,最後祇有兩個對象被釋放,那表明始終祇有兩個對象,那麽=右邊的對象是什麽?

具體來説,這個編譯器的處理,是把=的賦値,視同直接初始化的,move賦値,把右邊的移動到左邊,頭尾祇有一份對象。C++11的新操作。
#12
lyl9301302016-01-18 16:52
回复 6楼 TonyDeng
并不是想测试什么。只是当时学习看到这一段觉得有问题。当时不知道对已经初始化了的类是建立一个临时的变量来赋值,以为还是和初始化一样,那么按这个逻辑那析构函数的输出应该是Bye,Nanosmart!(已有的要干掉)而不是Bye,Nifty Foods!(新的还没出来)。
#13
TonyDeng2016-01-18 16:58
你編製的類,是引用構造,不會复製。
#14
TonyDeng2016-01-18 16:59
在C++中,不同的類,有不同的處理方式。比如對vector這種,無論怎麽給它添加數據,都是复製的。
#15
lyl9301302016-01-18 17:04
回复 13楼 TonyDeng
这一点还真没注意到,因为只是对着书上代码敲了一遍。如果改成指针的话,我估计就会变了。等会试一下
#16
TonyDeng2016-01-18 17:06
以下是引用lyl930130在2016-1-18 16:52:56的发言:

并不是想测试什么。只是当时学习看到这一段觉得有问题。当时不知道对已经初始化了的类是建立一个临时的变量来赋值,以为还是和初始化一样,那么按这个逻辑那析构函数的输出应该是Bye,Nanosmart!(已有的要干掉)而不是Bye,Nifty Foods!(新的还没出来)。


舊的C++會這樣,新標準下的就未必有臨時對象了。這本來是舊標準下某些編譯器就已經這麽做的,當時算非標,但新標把這種操作納入,就是標準操作。知識是會變的,也不是總有標準的,自己用著的是怎樣就怎樣。但就這個問題,正如我前面説的,對析構函數,少做動作是保護自己,沒什麽必要,不要在那裏寫什麽代碼,因爲你真的不能把握這函數什麽時候執行、甚至會不會執行。
#17
TonyDeng2016-01-18 17:08
C++有專研复製構造函數的啊,什麽時候要寫复製形式的構造函數、寫了之後接著應有一整套复製形式的函數配合,比如重載賦値操作符等。
#18
hjx11202016-01-18 17:17
析构函数在return 之前出现在那都是有可能的,不是楼主你想让它出现就出现的,这要看编译器的心情
#19
wmf20142016-01-18 17:18
回复 10楼 lyl930130
没仔细看你的输出结果,对第一个bye没看见。c++的类还不熟,你这种临时类释放的说法我还要复习复习!
不过就我理解的构造函数和析构函数类似于窗口的load和unload事件,原本你不需要做什么的,但有时需要初始化数据或画蛇添足显示退出提示,就交给设计者自己处理了。
1