最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中的構(gòu)造函數(shù)詳解

 更新時(shí)間:2021年09月16日 17:28:41   作者:天上掉下個(gè)我  
這篇文章主要介紹了C++ 中構(gòu)造函數(shù)的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下

普通變量的初始化

當(dāng)我們在定義一個(gè)變量不給它指定一個(gè)初始值時(shí),這對于全局變量和局部變量來說結(jié)果會(huì)不一樣。全局變量在程序裝入內(nèi)存時(shí) 就已經(jīng)分配好空間,程序運(yùn)行期間其地址不變,它會(huì)被初始化為全0(變量的每一位都為0)。但是局部變量定義在函數(shù)內(nèi)部,存儲(chǔ)在棧上,當(dāng)函數(shù)被調(diào)用時(shí),棧會(huì)分配一部分空間來存儲(chǔ)該局部變量(也就是只分配空間,而不管賦值),這時(shí)此空間的值是已經(jīng)有的,它是一個(gè)隨機(jī)的值,如果程序員不對它進(jìn)行初始化,將會(huì)產(chǎn)生不好的后果(如果將??臻g內(nèi)存的變量初始化工作交給編譯器,則每次函數(shù)調(diào)用都會(huì)被重新賦值,則會(huì)大大增加開銷)。

示例全局變量,這些對象會(huì)被賦一個(gè)默認(rèn)的初始值。如圖:

在這里插入圖片描述

整型被賦為0,字符為空字符,浮點(diǎn)數(shù)被賦為0.000000

構(gòu)造函數(shù)

對象和我們前面提到的基本類型的變量一樣,定義的時(shí)候也能夠被初始化。而這些初始化操作會(huì)比基本數(shù)據(jù)類型初始化更復(fù)雜一些,不僅涉及對類內(nèi)基本數(shù)據(jù)類型的初始化,還包括進(jìn)行動(dòng)態(tài)內(nèi)存分配,打開文件等操作。這時(shí)就需要為類設(shè)計(jì)一個(gè)構(gòu)造函數(shù)來專門負(fù)責(zé)這些操作,對象一旦創(chuàng)建就立即調(diào)用它,對其進(jìn)行強(qiáng)制初始化(這是強(qiáng)制執(zhí)行的)。

構(gòu)造函數(shù)屬于成員函數(shù)比較特殊的一種(與其他成員函數(shù)不同,它不能被顯式的調(diào)用,所以也沒有必要為它設(shè)置返回值),它在對象的初始化時(shí)起作用(設(shè)計(jì)類時(shí)往往將初始化功能在構(gòu)造函數(shù)中實(shí)現(xiàn)),我們希望創(chuàng)建出的所有變量都能被賦予有意義的能力,而不是未知的,可以在創(chuàng)建之后再次改變他,但在此之前若要使用它,將會(huì)發(fā)生意外,所以在制度上我們就要對其進(jìn)行嚴(yán)防死守(使其被創(chuàng)建后一定處于良好狀態(tài))。

構(gòu)造函數(shù)可以重載,可以編寫多個(gè)構(gòu)造函數(shù),參數(shù)列表不同。生成對象時(shí),將會(huì)根據(jù)參數(shù)列表的參數(shù)信息決定該調(diào)用哪個(gè)構(gòu)造函數(shù)。如果沒有對參數(shù)有任何交代,編譯器就認(rèn)為應(yīng)該調(diào)用無參構(gòu)造函數(shù)。

當(dāng)在局部空間或全局區(qū)創(chuàng)建自定義類型的對象時(shí),構(gòu)造函數(shù)會(huì)被自動(dòng)調(diào)用(設(shè)計(jì)好初始化后,每當(dāng)創(chuàng)建對象就會(huì)自動(dòng)調(diào)用構(gòu)造函數(shù)會(huì)使每一個(gè)對象都處于良好的隨時(shí)可用的狀態(tài))。如圖:

在這里插入圖片描述

以上演示是在類的外部對構(gòu)造函數(shù)進(jìn)行了定義,實(shí)際開發(fā)中,一般將類的定義部分放到頭文件中(.h),而類內(nèi)成員函數(shù)的實(shí)現(xiàn)放到實(shí)現(xiàn)文件中(.cc)中。這對我們在不改變類的定義的情況下修改他的成員函數(shù)提供了方便。這比在類內(nèi)直接實(shí)現(xiàn)有一個(gè)好處,就是不需要每次改變函數(shù)體都要重新編譯(前題是不改變函數(shù)聲明)。

明確一點(diǎn),如果在類內(nèi)對成員函數(shù)進(jìn)行了實(shí)現(xiàn),它將會(huì)被隱式地聲明為內(nèi)聯(lián)函數(shù)(由編譯器決定是否最終把它變?yōu)閮?nèi)聯(lián)函數(shù))。

一般超過5行代碼的函數(shù)就沒有必要設(shè)為內(nèi)聯(lián)函數(shù)了(函數(shù)內(nèi)限制在兩個(gè)表達(dá)式最好)。

在我們只定義了有參的構(gòu)造函數(shù)后,就不會(huì)有無參的構(gòu)造函數(shù)了,需要我們自己定義一個(gè)無參的構(gòu)造函數(shù)。

class MyArray
{
	char array_;
public:
	MyArray(char a_new_array='x'):array_(a_new_array);//給出默認(rèn)參數(shù)
	MyArray();
	void PrintMyArray();
};
//類實(shí)現(xiàn)省略
void test()
{
	MyArray a_long_array('c');//調(diào)用有參的構(gòu)造方法
	MyArray a_short_array();//調(diào)用無參的構(gòu)造方法
}

初始化方法一般給出形參列表,在這里對類內(nèi)成員賦初值(此時(shí)構(gòu)造函數(shù)的函數(shù)體還未開始執(zhí)行),我們這里是對其輸入了一個(gè)字符。構(gòu)造函數(shù)還可以調(diào)用其他類的構(gòu)造函數(shù)來初始化對象中的成員變量(這是編譯器自動(dòng)調(diào)用的,如在隱式的數(shù)據(jù)類型轉(zhuǎn)換時(shí))。當(dāng)然也可以在構(gòu)造函數(shù)函數(shù)體內(nèi)為成員變量賦值(這并不是初始化,執(zhí)行函數(shù)體后賦值之前,成員變量已經(jīng)有一個(gè)無意義的值了)。

MyArray::MyArray(char init_array)
{//進(jìn)入構(gòu)造函數(shù)體后成員變量已經(jīng)有值了!
	array_=init_array;//在函數(shù)體內(nèi)進(jìn)行賦值
	cout << "MyArray的構(gòu)造方法執(zhí)行了!\n";
}

形參列表具有立即性(在成員變量被創(chuàng)建時(shí)形參列表的值就立即為其初始化),而構(gòu)造函數(shù)體內(nèi)需要執(zhí)行賦值語句。對于一些自定義類型的成員變量進(jìn)行初始化,形參列表初始化往往比賦值語句效率更高。此外對于一些特殊的成員只能采用形參列表的方式進(jìn)行初始化。

一定會(huì)生成默認(rèn)構(gòu)造函數(shù)嗎?

前面我們說過,當(dāng)我們沒有編寫構(gòu)造函數(shù)時(shí),編譯器會(huì)為我們生成一個(gè)默認(rèn)的構(gòu)造函數(shù),對于初學(xué)者來說,這就夠了,但現(xiàn)在我們要強(qiáng)調(diào)幾點(diǎn)。

1.如果類中我們沒有定義構(gòu)造函數(shù)并且類中成員變量含有自定義類型成員變量時(shí),編譯器會(huì)生成默認(rèn)構(gòu)造函數(shù),并且調(diào)用自定義類型的構(gòu)造函數(shù)。

2.當(dāng)父類具有默認(rèn)構(gòu)造函數(shù)而子類沒有任何構(gòu)造函數(shù),當(dāng)生成子類對象時(shí),會(huì)生成子類的默認(rèn)構(gòu)造函數(shù),在這個(gè)函數(shù)中調(diào)用父類默認(rèn)構(gòu)造函數(shù)。

3.當(dāng)一個(gè)含有虛函數(shù)并且沒有構(gòu)造函數(shù)時(shí)編譯器會(huì)生成默認(rèn)的構(gòu)造函數(shù)。

4.出現(xiàn)菱形繼承時(shí),兩個(gè)父類分別進(jìn)行虛繼承,當(dāng)出現(xiàn)子類對象時(shí),子類會(huì)生成一個(gè)自己的默認(rèn)構(gòu)造函數(shù),在構(gòu)造函數(shù)內(nèi)調(diào)用兩個(gè)父類的構(gòu)造函數(shù)。

5.在定義類時(shí),直接為成員變量賦值,當(dāng)生成對象時(shí),會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)。

防止隱式類型轉(zhuǎn)換

如果構(gòu)造函數(shù)只有一個(gè)參數(shù)的話最好將此構(gòu)造函數(shù)聲明為ecplicit,他能防止編譯器將explicit的構(gòu)造函數(shù)進(jìn)行隱式類型轉(zhuǎn)換。

class MyArray
{
	char array_;
	double array_length_;
public:
	MyArray(double init);
	MyArray(char init);
	void PrintMyArray(MyArray a_array);
};
void MyArray::PrintMyArray(MyArray a_array)
{//理應(yīng)接受一個(gè)對象,有時(shí)會(huì)接受一個(gè)基本類型
//此時(shí)會(huì)進(jìn)行隱式類型轉(zhuǎn)換
	cout << "MyArray為:"<< a_array.array_length_ << "\n";
}
void test()
{
	MyArray first_array(3.0);
	first_array.PrintMyArray(5.0);//隱式的將5.0轉(zhuǎn)化為了MyArray對象
}

修改如下:

class MyArray
{
	char array_;
	double array_length_;
public:
	explicit MyArray(double init);
	explicit MyArray(char init);
	void PrintMyArray(MyArray a_array);
};

此時(shí)調(diào)用first_array.PrintMyArray(5.0)就會(huì)報(bào)錯(cuò)了。

賦值與初始化的區(qū)別

必須明確初始化和賦值的概念,當(dāng)一個(gè)對象剛被創(chuàng)建時(shí),對它的賦值操作為初始化,而賦值是修改一個(gè)已經(jīng)存在并且有值的對象。

int a_int=1;//初始化,a_int被創(chuàng)建出來并被立即初始化
a_int=2;//賦值,a_int已經(jīng)存在,沒有新的變量被創(chuàng)建出來

初始化出現(xiàn)在構(gòu)造函數(shù)中,而賦值出現(xiàn)在operator=操作符中。

一個(gè)對象只能被初始化一次,而賦值卻可以不限制次數(shù),在對象的聲明期內(nèi)都可以進(jìn)行。而且進(jìn)行賦值時(shí)可能會(huì)進(jìn)行類型轉(zhuǎn)換(此時(shí)會(huì)產(chǎn)生臨時(shí)對象)。

一個(gè)構(gòu)造函數(shù)的初始化可以借用另一個(gè)構(gòu)造函數(shù),他被稱為委托構(gòu)造函數(shù)。

class MyArray
{
	char array_;
	double array_length_{ 1.0 };
public:
	MyArray(double init, double in, double it);
	MyArray(double init);
	MyArray();
	double GetMyArrayLength();
	bool CompareMyArrayLength(MyArray a_array);
	void PrintMyArray(MyArray a_array);
};
MyArray::MyArray(double init, double in, double it)
{
	cout << "構(gòu)造函數(shù)1執(zhí)行了!" << endl;
}
MyArray::MyArray(double init) :MyArray{ init,init,init }
{
	cout << "構(gòu)造函數(shù)2執(zhí)行了!" << endl;
}
//其他函數(shù)實(shí)現(xiàn)略
void test()
{
	MyArray first_array{ 1.0,1.1,1.2 };
	MyArray second_array{ 2.0 };
}

輸出如下:

在這里插入圖片描述

在執(zhí)行構(gòu)造函數(shù)2時(shí)先利用構(gòu)造函數(shù)1進(jìn)行初始化操作。

對象的計(jì)數(shù)

有時(shí)我們希望知道我們定義的一個(gè)類有多少個(gè)對象,就可以這樣操作:

class MyArray
{
	static int sum_;
public:
	MyArray();
	~MyArray();
	static int GetMyArraySum() { return sum_; }
};
int MyArray::sum_ = 0;
MyArray::MyArray()
{
	sum_++;
}
MyArray::~MyArray()
{
	sum_--;
}
void test()
{
	MyArray first_array;
	MyArray second_array;
	MyArray forth_array;
	cout << "MyArray有" << MyArray::GetMyArraySum() << "個(gè)對象" << endl;
}

輸出如下:

在這里插入圖片描述

因?yàn)閯?chuàng)建對象的時(shí)候構(gòu)造函數(shù)一定會(huì)被調(diào)用,所以它能準(zhǔn)確的記錄當(dāng)前的對象數(shù)。

成員初始化的順序

一個(gè)類中成員的初始化順序和它們在類中被聲明的順序是一致的。編譯器會(huì)忽略構(gòu)造函數(shù)中的順序,這是因?yàn)閷ο蟮奈鰳?gòu)需要和對象的成員構(gòu)造順序相反的要求 。

所以在編程中,成員變量的初始化順序應(yīng)與類定義中的聲明順序保持一致。

class Employee
{//錯(cuò)誤示范
	string email_,first_name_,last_name_;
public:
	Employee(const char* first_name,const char* last_name):first_name_(first_name),last_name_(last_name),email_(first_name_+last_name_+"@163.com"){}

類中定義的email_是在first_和last_之前的,但程序卻用其他未初始化的成員變量來為它初始化。

類的引用成員

如果類中的某個(gè)費(fèi)靜態(tài)數(shù)據(jù)成員是一個(gè)引用的話,所有的引用必須被明確地初始化,所以在構(gòu)造函數(shù)中都要顯示初始化。

class MyArray
{
	YourArray& a_array_;
public:
	MyArray(YourArray&);
}
MyArray::MyArray(YourArray& init)//會(huì)被報(bào)錯(cuò)
{
}

這個(gè)成員引用有兩個(gè)特點(diǎn),一,在創(chuàng)建a_array_時(shí)就要為它綁定一個(gè)對象,二,一旦綁定后,就不能再綁定其他變量了。

構(gòu)造函數(shù)使用注意事項(xiàng)

1.除非必要不要在構(gòu)造函數(shù)內(nèi)做與初始化對象無關(guān)的事情,減少它的功能可以使每個(gè)函數(shù)功能更加明確,增加效率。

2.類的非靜態(tài)const成員和引用成員只能在構(gòu)造函數(shù)的初始化列表中進(jìn)行初始化,這是由const和引用自身特點(diǎn)決定的。

3.不能同時(shí)定義一個(gè)無參的構(gòu)造函數(shù)和一個(gè)參數(shù)全部為默認(rèn)值得構(gòu)造函數(shù)。

4.拷貝構(gòu)造函數(shù)的參數(shù)應(yīng)為引用傳遞,如果為傳值則會(huì)與有一個(gè)參數(shù)的構(gòu)造函數(shù)沖突。

參考

The C++ Programming Language (美) Bjarne Stroustrup

cpp參考:https://zh.cppreference.com

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java C++ 算法leetcode828統(tǒng)計(jì)子串中唯一字符乘法原理

    Java C++ 算法leetcode828統(tǒng)計(jì)子串中唯一字符乘法原理

    這篇文章主要為大家介紹了Java C++ 算法leetcode828統(tǒng)計(jì)子串中唯一字符乘法原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 解析C++哈夫曼樹編碼和譯碼的實(shí)現(xiàn)

    解析C++哈夫曼樹編碼和譯碼的實(shí)現(xiàn)

    本篇文章主要介紹了C++哈夫曼樹編碼和譯碼的實(shí)現(xiàn),詳細(xì)的講訴了哈夫曼樹編碼的原理,有需要的同學(xué)可以了解一下。
    2016-11-11
  • C++中棧結(jié)構(gòu)建立與操作詳細(xì)解析

    C++中棧結(jié)構(gòu)建立與操作詳細(xì)解析

    我們可以把棧理解成一個(gè)大倉庫,放在倉庫門口(棧頂)的貨物會(huì)優(yōu)先被取出,然后再取出里面的貨物。而從數(shù)據(jù)的邏輯結(jié)構(gòu)來看,棧結(jié)構(gòu)起始就是一種線性結(jié)構(gòu)
    2013-10-10
  • C語言自動(dòng)生成enum值和名字映射代碼

    C語言自動(dòng)生成enum值和名字映射代碼

    這篇文章主要介紹了C語言自動(dòng)生成enum值和名字映射代碼的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • 解讀C++11 原生字符串

    解讀C++11 原生字符串

    這篇文章主要介紹了C++11 原生字符串的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++11,感興趣的朋友可以了解下
    2020-08-08
  • C++ ReSharper2021激活碼永久有效

    C++ ReSharper2021激活碼永久有效

    ReSharperC++是為c/c++開發(fā)者打造的一款實(shí)用Visual Studio擴(kuò)展插件,這款插件旨在提升開發(fā)者的效率,今天給大家分享這款軟件的激活方法,需要C++ ReSharper2021激活碼的朋友參考下本文
    2021-06-06
  • C++ 輕量級(jí)對象JSON序列化實(shí)現(xiàn)詳情

    C++ 輕量級(jí)對象JSON序列化實(shí)現(xiàn)詳情

    本文以jsoncpp庫為基礎(chǔ),設(shè)計(jì)這樣一個(gè)可以支持一個(gè)函數(shù) 可以一行代碼 unmarshal /marshal 對象,需要的朋友小伙伴可以參考以下
    2021-09-09
  • C語言中volatile關(guān)鍵字的深入講解

    C語言中volatile關(guān)鍵字的深入講解

    在程序設(shè)計(jì)中,尤其是在C語言、C++、C#和Java語言中,使用volatile關(guān)鍵字聲明的變量或?qū)ο笸ǔ>哂信c優(yōu)化、多線程相關(guān)的特殊屬性,這篇文章主要給大家介紹了關(guān)于C語言volatile關(guān)鍵字的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • C++中類模板的應(yīng)用你了解多少

    C++中類模板的應(yīng)用你了解多少

    這篇文章主要為大家詳細(xì)介紹了C++中類模板的應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C語言 typedef:給類型起一個(gè)別名

    C語言 typedef:給類型起一個(gè)別名

    本文主要介紹C語言 typedef,這里整理了相關(guān)資料及簡單示例代碼幫助大家學(xué)習(xí)理解,有興趣的小伙伴可以參考下
    2016-08-08

最新評論

天祝| 翼城县| 博乐市| 台东县| 静安区| 乌拉特中旗| 正镶白旗| 芮城县| 南丹县| 山东省| 泗洪县| 满洲里市| 铜山县| 沙洋县| 灌云县| 和田县| 甘南县| 巴塘县| 泰安市| 东辽县| 武定县| 汽车| 广西| 浦江县| 波密县| 阳高县| 哈巴河县| 泊头市| 长治市| 玛多县| 乌什县| 岳普湖县| 铁岭县| 长乐市| 太和县| 霍林郭勒市| 邹城市| 祁东县| 绩溪县| 揭东县| 大埔县|