一個(gè)關(guān)于臨時(shí)對(duì)象和虛擬析構(gòu)函數(shù)的問題
在CU逛,別人問到這樣的一個(gè)問題,大致如下:
#include <iostream>
#include <string>
using namespace std;
class base


{
public:

virtual void print()
{cout<<"base::print()"<<endl;}
//virtual ~base(){}//增加虛析構(gòu)函數(shù),將導(dǎo)致輸出不一致。
};
class derived :public base


{
public:

virtual void print()
{cout<<"devrived::print()"<<endl;}
};
int main(int argc, char *argv[])


{
base* p1=&derived();
p1->print();

derived d;
base* p2=&d;
p2->print();

return 0;
}
加入虛擬析構(gòu)函數(shù)后,輸出為:
base::print()
devrived::print()
不加入虛擬析構(gòu)函數(shù),輸出則為:
devrived::print()
devrived::print()
我的解釋如下:
實(shí)際上,第一個(gè)賦值指向的是一個(gè)臨時(shí)對(duì)象,加入與沒有加入虛擬析構(gòu)函數(shù)的區(qū)別在于:加入之后,在derived類中會(huì)合成一個(gè)析構(gòu)函數(shù)以便調(diào)用base的虛擬析構(gòu)函數(shù),如果沒有加入的話那么就不會(huì)合成這個(gè)析構(gòu)函數(shù),所有的資源在main函數(shù)結(jié)束之后才回收.
因此,對(duì)于代碼: base* p1=&derived();
沒有加入虛擬析構(gòu)函數(shù)的時(shí)候因?yàn)閐erived()函數(shù)生成的臨時(shí)對(duì)象沒有被銷毀,因此對(duì)它的調(diào)用是對(duì)derived的調(diào)用;當(dāng)加入虛擬析構(gòu)函數(shù)之后,derived()函數(shù)生成的臨時(shí)對(duì)象在以上的賦值完成之后就會(huì)調(diào)用析構(gòu)函數(shù)進(jìn)行析構(gòu),這個(gè)時(shí)候再次對(duì)p1調(diào)用print函數(shù)時(shí),因?yàn)榕R時(shí)對(duì)象已經(jīng)析構(gòu),那么這個(gè)調(diào)用就是對(duì)base的調(diào)用了.
我做了一個(gè)實(shí)驗(yàn)的代碼,加了一些東西,大家看看~~
#include <iostream>
#include <string>
using namespace std;
class base


{
public:

virtual void print()
{cout<<"base::print()"<<endl;}

virtual ~base()
{cout << "~base()\n";}//增加虛析構(gòu)函數(shù),將導(dǎo)致輸出不一致。
};
class derived :public base


{
public:

virtual void print()
{cout<<"devrived::print()"<<endl;}
//virtual ~derived(){cout << "~derived()\n";}//增加虛析構(gòu)函數(shù),將導(dǎo)致輸出不一致。
};

int main(int argc, char *argv[])


{
derived *t = &derived();
base* p1 = t;
p1->print();

derived d;
base* p2=&d;
p2->print();

// 第一部分相當(dāng)于以下的代碼
// 用temp模擬臨時(shí)對(duì)象
derived temp;
derived *s = &temp;
base *p3 = s;
// 這次調(diào)用是對(duì)derived的函數(shù)調(diào)用
p3->print();
// 顯式地對(duì)temp進(jìn)行析構(gòu)
temp.base::~base();
// 析構(gòu)完后,同樣的一個(gè)內(nèi)存,卻是用base指針去解釋,
// 因此調(diào)用的是base的函數(shù)
p3->print();

return 0;
}



































加入虛擬析構(gòu)函數(shù)后,輸出為:
base::print()
devrived::print()
不加入虛擬析構(gòu)函數(shù),輸出則為:
devrived::print()
devrived::print()
我的解釋如下:
實(shí)際上,第一個(gè)賦值指向的是一個(gè)臨時(shí)對(duì)象,加入與沒有加入虛擬析構(gòu)函數(shù)的區(qū)別在于:加入之后,在derived類中會(huì)合成一個(gè)析構(gòu)函數(shù)以便調(diào)用base的虛擬析構(gòu)函數(shù),如果沒有加入的話那么就不會(huì)合成這個(gè)析構(gòu)函數(shù),所有的資源在main函數(shù)結(jié)束之后才回收.
因此,對(duì)于代碼: base* p1=&derived();
沒有加入虛擬析構(gòu)函數(shù)的時(shí)候因?yàn)閐erived()函數(shù)生成的臨時(shí)對(duì)象沒有被銷毀,因此對(duì)它的調(diào)用是對(duì)derived的調(diào)用;當(dāng)加入虛擬析構(gòu)函數(shù)之后,derived()函數(shù)生成的臨時(shí)對(duì)象在以上的賦值完成之后就會(huì)調(diào)用析構(gòu)函數(shù)進(jìn)行析構(gòu),這個(gè)時(shí)候再次對(duì)p1調(diào)用print函數(shù)時(shí),因?yàn)榕R時(shí)對(duì)象已經(jīng)析構(gòu),那么這個(gè)調(diào)用就是對(duì)base的調(diào)用了.
我做了一個(gè)實(shí)驗(yàn)的代碼,加了一些東西,大家看看~~





















































posted on 2006-02-16 23:24 那誰 閱讀(22346) 評(píng)論(8) 編輯 收藏 引用 所屬分類: C\C++