線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1055
推到 Plurk!
推到 Facebook!

運算子 "==" 的問題

答題得分者是:aftcast
qqmts0726
一般會員


發表:11
回覆:6
積分:8
註冊:2008-06-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-04-25 19:06:05 IP:60.29.xxx.xxx 訂閱
Dear all:

其實這個問題的標題下的還滿奇怪的 ,不過真的不知道怎麼表示比較好。

程式大概如下:

[code cpp]

class TA
{
public:
double dA;
TButton *Button;

TA();
~TA();
bool __fastcall operator==(const TA In);

};
TA::TA()
{
Button = new TButton(Application);
}
TA::~TA()
{
delete Button;
}
bool __fastcall TA::operator==(const TA In)
{
if(In.dA !=dA) return false;

return true;
};

[/code]




[code cpp]


class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
TA A1,A2;
__fastcall TForm1(TComponent* Owner);
};
[/code]


我在Form1上有一個Button,執行的內容 就是A1 == A2。

第一次執行的時候,程式很順利的可以執行。

第二次執行的時候,會發現有記憶體錯誤的問題。

那造成的原因是 運算子 == 離開函式的時候,會觸發解構子。

如此一來,A2 的 Button 就會被delete了。

但,正常來說,在解構的時候,delete 不用的元件是沒有錯的~

所以我就迷惘到底是我operater == 寫錯了,還是根本就不應該這樣用呢?


aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-04-26 00:36:37 IP:122.126.xxx.xxx 訂閱
這算是c++ 進階一點的觀念題。
解法一: 使用 參考型別


[code cpp]
class TA
{
public:
double dA;
TButton *Button;

TA();
~TA();

bool __fastcall operator==(const TA &In); // 注意這裡是傳參考!!!


};
TA::TA()
{
//Button = new TButton(Application);
// 這裡也很重要,不用能Application,否則會被delete二次,一次是Application死時,一次是你自己的物件將死之時。
// 凡自己要處理死的部份,即自己解構,就不該用owner的方式。
Button = new TButton((void*)0);
}
TA::~TA()
{
delete Button;
}
bool __fastcall TA::operator==(const TA &In)
// 注意這裡是傳參考!!!
{
if(In.dA !=dA) return false;

return true;
};

[/code]



解法二: 使用copy constructor,因為傳入的方式是「傳值」所以一定要有這個。當然,你沒有的話, compiler會幫你搞出一個,但它用的方式,僅copy你的資料成員,故你的Button的指標內容第一次是被copy到了。但也因為「臨時的」那個局部物件,離開那個函式的時候,會叫解構。於是你Button所指的東西就被幹掉。所以第二次必死。若有寫copy constructor,自己實作new的部份,那麼臨時的那個解的就是"臨時new出的那個"。 (稍要用力的去理解一下這裡)


[code cpp]
class TA
{
public:
double dA;
TButton *Button;

TA();
~TA();
TA(TA &src); // 考備建構式

bool __fastcall operator==(const TA In);
// 傳值

};
TA::TA()
{
//Button = new TButton(Application);
// 這裡也很重要,不用能Application,否則會被delete二次,一次是Application死時,一次是你自己的物件將死之時。
// 凡自己要處理死的部份,即自己解構,就不該用owner的方式。
Button = new TButton((void*)0);
}
TA::~TA()
{
delete Button;
}
bool __fastcall TA::operator==(const TA In) // 傳值
{
if(In.dA !=dA) return false;

return true;
};

//這裡是新加入的
TA::TA(TA &src)
{
dA = src.dA;
Button = new TButton((void*)0);
}

[/code]

最後要注意你 new button 那裡的寫法,要用小技巧才可以!!! 否則你程式結束的時候必然又會AV一次!

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2011-04-25 10:38:59, 註解 無‧
系統時間:2017-12-18 7:26:22
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!