亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

普通變量的初始化

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

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

在這里插入圖片描述

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

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

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

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

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

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

在這里插入圖片描述

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

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

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

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

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

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

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í)行賦值語(yǔ)句。對(duì)于一些自定義類(lèi)型的成員變量進(jìn)行初始化,形參列表初始化往往比賦值語(yǔ)句效率更高。此外對(duì)于一些特殊的成員只能采用形參列表的方式進(jìn)行初始化。

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

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

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

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

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

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

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

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

如果構(gòu)造函數(shù)只有一個(gè)參數(shù)的話(huà)最好將此構(gòu)造函數(shù)聲明為ecplicit,他能防止編譯器將explicit的構(gòu)造函數(shù)進(jìn)行隱式類(lèi)型轉(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è)對(duì)象,有時(shí)會(huì)接受一個(gè)基本類(lèi)型
//此時(shí)會(huì)進(jìn)行隱式類(lèi)型轉(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對(duì)象
}

修改如下:

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è)對(duì)象剛被創(chuàng)建時(shí),對(duì)它的賦值操作為初始化,而賦值是修改一個(gè)已經(jīng)存在并且有值的對(duì)象。

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

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

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

一個(gè)構(gòu)造函數(shù)的初始化可以借用另一個(gè)構(gòu)造函數(shù),他被稱(chēng)為委托構(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)行初始化操作。

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

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

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è)對(duì)象" << endl;
}

輸出如下:

在這里插入圖片描述

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

成員初始化的順序

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

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

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"){}

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

類(lèi)的引用成員

如果類(lèi)中的某個(gè)費(fèi)靜態(tài)數(shù)據(jù)成員是一個(gè)引用的話(huà),所有的引用必須被明確地初始化,所以在構(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è)對(duì)象,二,一旦綁定后,就不能再綁定其他變量了。

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

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

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

3.不能同時(shí)定義一個(gè)無(wú)參的構(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é)

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

相關(guān)文章

  • C++實(shí)現(xiàn)校園導(dǎo)游系統(tǒng)

    C++實(shí)現(xiàn)校園導(dǎo)游系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)校園導(dǎo)游系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語(yǔ)言中的結(jié)構(gòu)體內(nèi)嵌函數(shù)用法

    C語(yǔ)言中的結(jié)構(gòu)體內(nèi)嵌函數(shù)用法

    這篇文章主要介紹了C語(yǔ)言中的結(jié)構(gòu)體內(nèi)嵌函數(shù)用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++中傳值、傳地址和傳引用究竟有哪些區(qū)別

    C++中傳值、傳地址和傳引用究竟有哪些區(qū)別

    指針是一個(gè)變量,只不過(guò)這個(gè)變量存儲(chǔ)的是一個(gè)地址,指向內(nèi)存的一個(gè)存儲(chǔ)單元,而引用跟原來(lái)的變量實(shí)質(zhì)上是同一個(gè)東西,只不過(guò)是原變量的一個(gè)別名而已,這篇文章主要給大家介紹了關(guān)于C++中傳值、傳地址和傳引用究竟有哪些區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • 詳解C++語(yǔ)法中的虛繼承和虛基類(lèi)

    詳解C++語(yǔ)法中的虛繼承和虛基類(lèi)

    本文主要介紹了C++語(yǔ)法中的虛繼承和虛基類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • C語(yǔ)言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊(cè)功能

    C語(yǔ)言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊(cè)功能

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Linux搭建C++開(kāi)發(fā)調(diào)試環(huán)境的方法步驟

    Linux搭建C++開(kāi)發(fā)調(diào)試環(huán)境的方法步驟

    這篇文章主要介紹了Linux搭建C++開(kāi)發(fā)調(diào)試環(huán)境的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 解析c語(yǔ)言中"函數(shù)調(diào)用中缺少哨兵"的情況分析

    解析c語(yǔ)言中"函數(shù)調(diào)用中缺少哨兵"的情況分析

    本篇文章是對(duì)c語(yǔ)言中"函數(shù)調(diào)用中缺少哨兵"的情況進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++設(shè)計(jì)模式之簡(jiǎn)單工廠(chǎng)模式的實(shí)現(xiàn)示例

    C++設(shè)計(jì)模式之簡(jiǎn)單工廠(chǎng)模式的實(shí)現(xiàn)示例

    這篇文章主要給大家介紹了關(guān)于C++設(shè)計(jì)模式之簡(jiǎn)單工廠(chǎng)模式的相關(guān)資料,簡(jiǎn)單工廠(chǎng)模式,主要用于創(chuàng)建對(duì)象,添加類(lèi)時(shí),不會(huì)影響以前的系統(tǒng)代碼,需要的朋友可以參考下
    2021-06-06
  • C++中的三種繼承public,protected,private詳細(xì)解析

    C++中的三種繼承public,protected,private詳細(xì)解析

    我們已經(jīng)知道,在基類(lèi)以private方式被繼承時(shí),其public和protected成員在子類(lèi)中變?yōu)閜rivate成員。然而某些情況下,需要在子類(lèi)中將一個(gè)或多個(gè)繼承的成員恢復(fù)其在基類(lèi)中的訪(fǎng)問(wèn)權(quán)限
    2013-09-09
  • String底層函數(shù)的實(shí)現(xiàn)方式詳解

    String底層函數(shù)的實(shí)現(xiàn)方式詳解

    這篇文章主要介紹了String底層函數(shù)的實(shí)現(xiàn)方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09

最新評(píng)論