欧美特黄不卡,涩涩视频在线,成人国产精品一区二区网站,亚洲一区二区三区欧美

當(dāng)前位置:雨林木風(fēng)下載站 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

由始至終----構(gòu)造與析構(gòu)(轉(zhuǎn)轉(zhuǎn))

由始至終----構(gòu)造與析構(gòu)(轉(zhuǎn)轉(zhuǎn))

更新時間:2022-05-03 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

由始至終

 ----構(gòu)造與析構(gòu)

作者:HolyFire

我們在平時的生活中一般會總結(jié)出一些規(guī)律,早上起床會刷牙洗臉,晚上會洗澡睡覺,這些都成了慣例。使用瓶裝調(diào)味品時先將瓶蓋打開,用完后將瓶蓋蓋上。這是一種好習(xí)慣。但是有些人不同,他們往往偷懶,一個常常不刷牙不洗臉不洗澡的人會有體味,東西放得亂七八糟的人生房間很不整潔。這些都是我們不希望看到的。當(dāng)然編程中我們也不希望代碼亂七八糟。

使用一個未初始化的變量簡直就是災(zāi)難,使用一個未初始化的指針將導(dǎo)致崩潰。這是我的忠告。在C++中初始化不會有附加的效果,不會降低效率,我們要做的是養(yǎng)成好習(xí)慣,產(chǎn)生一個對象的時候就將它初始化。

對于

Object.Init();

Object.Free();

這樣的調(diào)用并不是很困難,要記住他也不是難事,但是誰都不能保證他永遠(yuǎn)不會忘記,更糟糕的是

Object.Init();

Object.Free();

沒有配對使用

Object.Init();

Object.Free();

Object.Free();



Object.Init();

Object.Init();

Object.Free();

會帶來什么樣的結(jié)果,誰也不知道,而且這樣的錯誤,編譯器不會報(bào)錯。這是多么可怕的錯誤,一個程序員最怕遇上的就是這樣的邏輯錯誤,它可能為了找這樣的一個錯誤花上一整天時間。

讓我們看看有什么好的辦法。

一個對象按時間來分析,一般有三個階段,出生,活動,死亡。與我們要做的有什么相關(guān)之處呢,初始化,運(yùn)行,釋放。很好,對照一下,我們發(fā)現(xiàn)在對象出生的時候初始化,死亡的時候釋放,如果這一切能用這樣的機(jī)制來操作,我們就再也不用擔(dān)心會由于忘記或錯誤的使用帶來麻煩了。

C++里就提供了這樣的機(jī)制。使用他有個約定

class Object{

public:

 Object(); //與類同名的函數(shù),該函數(shù)沒有返回值,叫做構(gòu)造函數(shù)

~Object();//類似的,在構(gòu)造函數(shù)名前加一個取反符號,叫做析構(gòu)函數(shù)

};

構(gòu)造函數(shù)將在對象產(chǎn)生的時候調(diào)用

析構(gòu)函數(shù)將在對象銷毀的時候調(diào)用

調(diào)用的過程和實(shí)現(xiàn)方法由編譯器完成,我們只要記住他們調(diào)用的時間就行了,而且他們的調(diào)用是自動完成的,不需要我們控制。

#include <iostream>

using namespace std;

class Object{

public:

 Object(){ cout << "Object ON!" << endl; }

 ~Object(){ cout << "Object OFF!" << endl; }

};

void main()

{

 Object o;

}

運(yùn)行結(jié)果

Object ON!

Object OFF!

構(gòu)在函數(shù)和析構(gòu)函數(shù)確實(shí)的執(zhí)行了

現(xiàn)在我們來一個應(yīng)用的例子

一個字符串類,它需要保存字符串的內(nèi)容,但是它不知道字符串的大小,那么設(shè)計(jì)這個字符串類的時候,保存字符串的成員變量就不能用固定大小的數(shù)組,而是用可以間接操作數(shù)組的指針。

#include <iostream>

#include <string.h>

using namespace std;

class string{

private:

 char * data;

public:

 string(){ data = NULL; }

 string( char * str )

{

cout << "Copy string: " << str << endl;

data = new char[ strlen(str) + 1 ];

memcpy( data , str , strlen(str) + 1 );

}

 char * Data(){ return data; }

 ~string()

{

if( data )

 {

 cout << "Free string: " << data << endl;

 delete data;

 }

}

};

void main()

{

 {

string s("abcd");

 cout <<"Show String: " << s.Data() <<endl;

}

cin.get();

}

Copy string: abcd //執(zhí)行了string::string( char * str ) 構(gòu)造函數(shù)

Show String: abcd

Free string: abcd //由于在{}中產(chǎn)成的對象是臨時對象,它的生命期在}后就結(jié)束了,所以string::~string() 析構(gòu)函數(shù)被調(diào)用

申請內(nèi)存和釋放內(nèi)存的操作自動完成了,構(gòu)造函數(shù)和析構(gòu)函數(shù)的目的在于一個類可以象普通類型一樣初始化和釋放,從而保證了封裝。

上面的例子有兩個構(gòu)造函數(shù),這么什么大不了的,我們看過《面面俱到----重載》得都知道,重載的把戲。

要注意的是構(gòu)造函數(shù)可以有參數(shù),在繼承中如何處理呢。

class mystring : public string{

public:

 mystring( char * str ):string( str ){ }

}

mystring( char * str ):string( str )

記住這樣的形式,給自己的父類傳遞函數(shù)就用這樣的書寫格式,這是一個約定。

構(gòu)造函數(shù)后面加上一個:表示后面是一個初始化序列,說它是一個序列是因?yàn)樗梢猿跏蓟鄠成員變量,在初始化序列里調(diào)用向父類傳遞參數(shù)是為了保證類的產(chǎn)生的順序,先產(chǎn)生父類,然后是子類。使用初始化有個好處就是可以提高效率。

string(){ data = NULL; }

可以改寫成

string():data(NULL){ }

他的作用是產(chǎn)生成員變量char * data時將他的值置為NULL。從而少了data = NULL;這步操作。

注意,這里構(gòu)造和析構(gòu)有一個順序問題,就是構(gòu)造時應(yīng)該從基類開始按繼承的層次順序調(diào)用,析構(gòu)的時候順序正好相反。這樣處理是因?yàn),子類可能在?gòu)造函數(shù)里使用父類的成員變量,如果父類還沒有創(chuàng)建,那就會有問題,而析構(gòu)的時候,如果父類先析構(gòu),也會有這樣的問題。

析構(gòu)函數(shù)還有一個能否正確運(yùn)行的問題。

#include <iostream>

using namespace std;

class One{

public:

 One(){ cout << "One ON!" << endl; }

 ~One(){ cout << "One OFF!" << endl; }

};

class Two : public One{

public:

 Two(){ cout << "Two ON!" << endl; }

 ~Two(){ cout << "Two OFF!" << endl; }

};

class Three : public Two{

public:

 Three(){ cout << "Three ON!" << endl; }

 ~Three(){ cout << "Three OFF!" << endl; }

};

void main()

{

 Three three;

}

運(yùn)行結(jié)果

One ON!

Two ON!

Three ON!

Three OFF!

Two OFF!

One OFF!

正確

void main()

{

 Three * three = new Three;

delete three;

}

運(yùn)行結(jié)果

One ON!

Two ON!

Three ON!

Three OFF!

Two OFF!

One OFF!

正確

void main()

{

 One * three = new Three;

delete three;

}

運(yùn)行結(jié)果

One ON!

Two ON!

Three ON!

One OFF!

不好了,Two和Three的析構(gòu)都沒有運(yùn)行,怎么會這樣,原來One * three指出了指針指向的是一個One類的對象。如何得到正確的結(jié)果呢,如果能讓One類記住被繼承后的變化就好了。

對了!虛函數(shù),在《后入為主----虛函數(shù)》中可以知道,虛函數(shù)有這個特性,不信試試看。

class One{

public:

 One(){ cout << "One ON!" << endl; }

 virtual ~One(){ cout << "One OFF!" << endl; }

};

void main()

{

 One * three = new Three;

delete three;

}

運(yùn)行結(jié)果

One ON!

Two ON!

Three ON!

Three OFF!

Two OFF!

One OFF!

正確

這個特點(diǎn)很重要,我們要牢牢記住,我們稱這種方法為“虛析構(gòu)”,在多態(tài)里運(yùn)用非常廣泛,也是編寫可復(fù)用代碼的一個重要技巧。

構(gòu)造和析構(gòu)的作用機(jī)制就是自動化,簡化編程的復(fù)雜度。還有要記住的是,在一個類的構(gòu)造函數(shù)里分配了的資源盡量要記得在該類的析構(gòu)函數(shù)里釋放,當(dāng)然也允許提前釋放,你可以在析構(gòu)函數(shù)里判斷它是否已經(jīng)釋放,如果沒有就釋放。這就是----由始至終,它間接的描述了一個對象的生和死(記住這一點(diǎn)很重要,因?yàn)槲乙院髸v到如何運(yùn)用這個特性控制對象的生死)。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統(tǒng)下載排行

主站蜘蛛池模板: 辽中县| 元朗区| 溆浦县| 电白县| 广汉市| 汕尾市| 泗洪县| 锡林郭勒盟| 平塘县| 政和县| 太原市| 甘泉县| 仲巴县| 濮阳县| 丹东市| 德格县| 余庆县| 略阳县| 大荔县| 广德县| 山丹县| 民勤县| 白玉县| 凤阳县| 阜阳市| 新龙县| 庆阳市| 张家界市| 仁化县| 衡阳县| 东丽区| 玉溪市| 白河县| 南木林县| 西贡区| 邓州市| 剑河县| 腾冲县| 页游| 瓮安县| 嘉禾县|