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

C++中類的默認(rèn)成員函數(shù)詳解

 更新時(shí)間:2022年01月25日 16:14:24   作者:你好,馮同學(xué)  
大家好,本篇文章主要講的是C++中類的默認(rèn)成員函數(shù)詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下

C++中,對(duì)于任意一個(gè)類,都會(huì)為我們提供4個(gè)默認(rèn)的成員函數(shù)(如果我們不顯示的去聲明)——構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、賦值函數(shù)。這些函數(shù)在特定的情況下會(huì)被自動(dòng)調(diào)用,但自動(dòng)調(diào)用并不意味著它們能像用戶所期望的那樣能實(shí)現(xiàn)特定的功能或者完成特定的任務(wù),更多的時(shí)候需要我們自己實(shí)現(xiàn)這些函數(shù)的功能

A();                         //默認(rèn)的構(gòu)造函數(shù)
~A();                        //析構(gòu)函數(shù)
A(const A&);                 //默認(rèn)的拷貝函數(shù)
A& operator = (const A& a);  //默認(rèn)賦值函數(shù)

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

構(gòu)造函數(shù)是一個(gè)特殊的成員函數(shù),名字與類名相同,通過(guò)類創(chuàng)建對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,保證每個(gè)數(shù)據(jù)成員都有 一個(gè)合適的初始值,并且在對(duì)象的生命周期內(nèi)只調(diào)用一次。構(gòu)造函數(shù)的功能是由類的實(shí)現(xiàn)者實(shí)現(xiàn),根據(jù)實(shí)際情況設(shè)計(jì)函數(shù)體和函數(shù)參數(shù),構(gòu)造函數(shù)必須有一個(gè),或者可以有多個(gè)。

class Person
{
public:
   //無(wú)參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù)都稱為默認(rèn)構(gòu)造函數(shù),并且默認(rèn)構(gòu)造函數(shù)只能有一個(gè)。
   //注意:無(wú)參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒(méi)寫編譯器默認(rèn)生成的構(gòu)造函數(shù),都可以認(rèn)為是默認(rèn)成員函數(shù)。
   Person(string name = "馮同學(xué)", int age = 18)
   {
     _name = name;
     _age = age;
   }
   //打印信息
   void Print() const
   {
     cout << "姓名:" << _name << "——年齡:" << _age << endl;
   }
   
private:
  string _name;
  int _age;
};

int main()
{
	Person A;//調(diào)用全缺省的構(gòu)造函數(shù)
	Person B("風(fēng)同學(xué)");//調(diào)用半缺省的構(gòu)造函數(shù)
	Person C("瘋同學(xué)",20);
	A.Print();
	B.Print();
	C.Print();
}

在這里插入圖片描述

關(guān)于編譯器生成的默認(rèn)成員函數(shù),很多人會(huì)有疑惑:在我們不實(shí)現(xiàn)構(gòu)造函數(shù)的情況下,編譯器會(huì)生成默認(rèn)的構(gòu)造函數(shù)。但是看起來(lái)默認(rèn)構(gòu)造函數(shù)又沒(méi)什么用?A對(duì)象調(diào)用了編譯器生成的默認(rèn)構(gòu)造函數(shù),但是A對(duì)象_name是空字符串,_age依舊是隨機(jī)值。也就說(shuō)在這里編譯器生成的默認(rèn)構(gòu)造函數(shù)并沒(méi)有什么用??

class Person
{
public:
	void Print() const
	{
		cout << "姓名:" << _name << "——年齡:" << _age << endl;
	}
private:
	string _name;
	int _age;
};

int main()
{
	Person A;
	A.Print();
}

在這里插入圖片描述

解答:C++把類型分成內(nèi)置類型(基本類型)和自定義類型。內(nèi)置類型就是語(yǔ)法已經(jīng)定義好的類型:如
int/char…,自定義類型就是我們使用class/struct/union自己定義的類型,看看下面的程序,就會(huì)發(fā)現(xiàn)
編譯器生成默認(rèn)的構(gòu)造函數(shù)會(huì)對(duì)自定類型成員B調(diào)用的它的默認(rèn)成員函數(shù)

class B
{
public:
	B(int b)
	{
		_b = b;
	}
private:
	int _b = 0;
};

class A
{
private:
	int _a;
	B bb;
};
int main()
{
	A aa;
	return 0;
}

在這里插入圖片描述

在A類中,用B類創(chuàng)建了一個(gè)bb對(duì)象,bb對(duì)象就會(huì)調(diào)用構(gòu)造函數(shù),因?yàn)槭亲远x的構(gòu)造函數(shù),編譯器就不會(huì)給出默認(rèn)的構(gòu)造函數(shù),所以就會(huì)報(bào)錯(cuò)。如果將B的構(gòu)造函數(shù)改為無(wú)參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù),那么程序就對(duì)了,這樣也就證明了自定類型成員會(huì)調(diào)用的它的默認(rèn)成員函數(shù)

構(gòu)造函數(shù)的特點(diǎn)

函數(shù)名與類名相同。無(wú)返回值。對(duì)象實(shí)例化時(shí)編譯器自動(dòng)調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)。構(gòu)造函數(shù)可以重載。在定義類時(shí),如果沒(méi)有定義構(gòu)造函數(shù),則C++編譯器會(huì)自動(dòng)提供一個(gè)默認(rèn)構(gòu)造函數(shù)(沒(méi)有參數(shù)),一旦我們定義構(gòu)造函數(shù),C++編譯器就不會(huì)提供默認(rèn)構(gòu)造函數(shù)無(wú)參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒(méi)寫編譯器默認(rèn)生成的構(gòu)造函數(shù),都可以認(rèn)為是默認(rèn)成員函數(shù)。并且默認(rèn)構(gòu)造函數(shù)只能有一個(gè)(如果默認(rèn)構(gòu)造函數(shù)出現(xiàn)多個(gè),在創(chuàng)建對(duì)象調(diào)用構(gòu)造函數(shù)時(shí),可能會(huì)出現(xiàn)二義性)

二、析構(gòu)函數(shù)

與構(gòu)造函數(shù)相反的是析構(gòu)函數(shù),析構(gòu)函數(shù)不是完成對(duì)象的銷毀,局部對(duì)象銷毀工作是由編譯器完成的。而對(duì)象在銷毀時(shí)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù),完成類的一些資源清理工作,例如在構(gòu)造函數(shù)中,我們?yōu)槌蓡T變量申請(qǐng)了內(nèi)存,我們就可以在析構(gòu)函數(shù)中將申請(qǐng)的內(nèi)存釋放

class Person
{
public:
	Person(string name = "馮同學(xué)", int age = 18)
	{
		_name = name;
		_age = age;
	}

	void Print() const
	{
		cout << "姓名:" << _name << "——年齡:" << _age << endl;
	}
	
	~Person()
	{
		cout << _name << "正在調(diào)用~Person()" << endl;
	}

private:
	string _name;
	int _age;
};

int main()
{
	Person A;
	Person B("風(fēng)同學(xué)");
	Person C("瘋同學(xué)", 20);
	A.Print();
	B.Print();
	C.Print();
}

在這里插入圖片描述

關(guān)于編譯器自動(dòng)生成的析構(gòu)函數(shù),是否會(huì)完成一些事情呢?下面的程序我們會(huì)看到,編譯器生成的默認(rèn)析構(gòu)函數(shù),對(duì)會(huì)自定類型成員調(diào)用它的析構(gòu)函數(shù)。

class B
{
public:
	B(int b = 0)
	{
		_b = b;
	}

	~B()
	{
		cout << "正在調(diào)用~B()" << endl;
	}

private:
	int _b = 0;
};

class A
{

private:
	int _a;
	B bb;
};

int main()
{
	A aa;
	return 0;
}

在這里插入圖片描述

析構(gòu)函數(shù)的特點(diǎn)

析構(gòu)函數(shù)名是在類名前加上字符 ~。無(wú)參數(shù)無(wú)返回值。一個(gè)類有且只有一個(gè)析構(gòu)函數(shù)。若未顯式定義,系統(tǒng)會(huì)自動(dòng)生成默認(rèn)的析構(gòu)函數(shù)。對(duì)象生命周期結(jié)束時(shí),C++編譯系統(tǒng)系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)。

三、拷貝構(gòu)造函數(shù)

拷貝構(gòu)造函數(shù)是一個(gè)特殊的構(gòu)造函數(shù)(構(gòu)造函數(shù)的重載形式)。用基于同一類的已經(jīng)存在的一個(gè)對(duì)象拷貝初始化另一個(gè)馬上創(chuàng)建的對(duì)象。

class Person
{
public:
	Person(string name = "馮同學(xué)", int age = 18)
	{
		_name = name;
		_age = age;
	}

	void Print() const
	{
		cout << "姓名:" << _name << "——年齡:" << _age << endl;
	}
	
	Person(const Person& p)
	{
		_name = p._name;
		_age = p._age;
	}
	
private:
	string _name;
	int _age;
};

int main()
{
	Person f("風(fēng)同學(xué)", 20);
	Person l(f);
	f.Print();
	l.Print();
}

在這里插入圖片描述

如果沒(méi)有定義拷貝構(gòu)造函數(shù),C++編譯器也會(huì)提供一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),不過(guò)該函數(shù)實(shí)現(xiàn)的是一個(gè)淺拷貝功能(將拷貝源按字節(jié)序賦值給拷貝對(duì)象)。淺拷貝對(duì)內(nèi)置類型基本存在什么影響,但對(duì)于在堆上開(kāi)辟的對(duì)象會(huì)存在安全隱患,來(lái)看看一下程序

class Person
{
public:
	Person(int age = 18)
	{
		_name = new string("馮同學(xué)");
		_age = age;
	}

	~Person()
	{
		cout << "正在調(diào)用~Person()——" << _name << endl;
		delete _name;
		_name = nullptr;
	}
	
private:
	string* _name;
	int _age;
};

int main()
{
	Person f(20);
	Person l(f);
}

在這里插入圖片描述

在這里插入圖片描述

通過(guò)打印的結(jié)果我們可以發(fā)現(xiàn)用對(duì)象 f 去拷貝構(gòu)造對(duì)象 l 時(shí),f 中的_name和 l 中的_name指向同一塊內(nèi)存空間(010C5440),并且在調(diào)用析構(gòu)函數(shù)時(shí),對(duì)同一塊內(nèi)存空間進(jìn)行了兩次釋放,最終導(dǎo)致了程序崩潰,這就是淺拷貝帶來(lái)的程序安全隱患。
不過(guò)我們可以將淺拷貝轉(zhuǎn)換為深拷貝從而解決問(wèn)題

//自己實(shí)現(xiàn)拷貝構(gòu)造函數(shù)
Person(const Person& p)
	{
		_name = new string;
		*_name = *p._name;
		_age = p._age;
	}

在這里插入圖片描述

先申請(qǐng)內(nèi)存,在進(jìn)行賦值就很好解決了淺拷貝問(wèn)題

拷貝構(gòu)造函數(shù)的特點(diǎn)

拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個(gè)重載形式??截悩?gòu)造函數(shù)的參數(shù)只有一個(gè)且必須使用引用傳參,使用傳值方式會(huì)引發(fā)無(wú)窮遞歸調(diào)用。若未顯示定義,系統(tǒng)生成默認(rèn)的拷貝構(gòu)造函數(shù)。 默認(rèn)的拷貝構(gòu)造函數(shù)對(duì)象按內(nèi)存存儲(chǔ)按字節(jié)序完成拷貝,這種拷貝我們叫做淺拷貝,或者值拷貝。

四、賦值函數(shù)(賦值運(yùn)算符重載)

賦值函數(shù)和拷貝構(gòu)造函數(shù)有點(diǎn)類似,不過(guò)賦值函數(shù)只是把一個(gè)已存在的對(duì)象賦值給另一個(gè)已存在的對(duì)象,使得那個(gè)已存在的對(duì)象具有和原對(duì)象相同的狀態(tài)。

class Person
{
public:
	Person(string name = "馮同學(xué)", int age = 18)
	{
		_name = name;
		_age = age;
	}

	Person& operator=(const Person& p)
	{
		_name = p._name;
		_age = p._age;
	}
	
	void Print() const
	{
		cout << "姓名:" << _name << "——年齡:" << _age << endl;
	}
	
private:
	string _name;
	int _age;
};

int main()
{
	Person f("風(fēng)同學(xué)", 21);
	Person l("鳳同學(xué)", 20);
	f = l;
	f.Print();
	l.Print();
}

在這里插入圖片描述

賦值函數(shù)的特點(diǎn)

使用關(guān)鍵字operator(所有的運(yùn)算符重載都會(huì)使用這個(gè)關(guān)鍵字)返回值為類的引用(返回*this)不能改變運(yùn)算符的優(yōu)先級(jí)/結(jié)合性/操作數(shù)個(gè)數(shù)一個(gè)類如果沒(méi)有顯式定義賦值運(yùn)算符重載,編譯器也會(huì)生成一個(gè),完成對(duì)象按字節(jié)序的值拷貝。

總結(jié)

到此這篇關(guān)于C++中類的默認(rèn)成員函數(shù)詳解的文章就介紹到這了,更多相關(guān)C++成員函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ipv6實(shí)現(xiàn)tcp編程示例

    ipv6實(shí)現(xiàn)tcp編程示例

    這篇文章主要介紹了ipv6實(shí)現(xiàn)tcp編程示例,需要的朋友可以參考下
    2014-03-03
  • C++實(shí)現(xiàn)簡(jiǎn)易圖書館管理系統(tǒng)

    C++實(shí)現(xiàn)簡(jiǎn)易圖書館管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 詳解C++的模板中typename關(guān)鍵字的用法

    詳解C++的模板中typename關(guān)鍵字的用法

    在C++的Template中我們經(jīng)??梢砸?jiàn)到使用typename來(lái)定義類型名稱,更加具體的我們就在接下來(lái)為大家詳解C++的模板中typename關(guān)鍵字的用法,需要的朋友可以參考下:
    2016-06-06
  • C++ 再識(shí)類和對(duì)象

    C++ 再識(shí)類和對(duì)象

    類是創(chuàng)建對(duì)象的模板,一個(gè)類可以創(chuàng)建多個(gè)對(duì)象,每個(gè)對(duì)象都是類類型的一個(gè)變量;創(chuàng)建對(duì)象的過(guò)程也叫類的實(shí)例化。每個(gè)對(duì)象都是類的一個(gè)具體實(shí)例(Instance),擁有類的成員變量和成員函數(shù)
    2021-10-10
  • C++基于Floyd算法實(shí)現(xiàn)校園導(dǎo)航系統(tǒng)

    C++基于Floyd算法實(shí)現(xiàn)校園導(dǎo)航系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++基于Floyd算法實(shí)現(xiàn)校園導(dǎo)航系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語(yǔ)言自定義實(shí)現(xiàn)strlen函數(shù)的3種方法總結(jié)

    C語(yǔ)言自定義實(shí)現(xiàn)strlen函數(shù)的3種方法總結(jié)

    這篇文章帶大家了解C語(yǔ)言中自定義實(shí)現(xiàn)strlen函數(shù)的3種方法,計(jì)數(shù)器,遞歸以及指針,這三種方法通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • 淺談C++的淺拷貝出現(xiàn)的錯(cuò)誤

    淺談C++的淺拷貝出現(xiàn)的錯(cuò)誤

    下面小編就為大家?guī)?lái)一篇淺談C++的淺拷貝出現(xiàn)的錯(cuò)誤。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • C++中二維map實(shí)現(xiàn)讀和寫

    C++中二維map實(shí)現(xiàn)讀和寫

    在C++中,可以使用std::map來(lái)實(shí)現(xiàn)二維映射,本文主要介紹了C++中二維map實(shí)現(xiàn)讀和寫,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程

    VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程

    這篇文章主要介紹了VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程,涉及VC針對(duì)系統(tǒng)進(jìn)程的相關(guān)操作技巧,需要的朋友可以參考下
    2015-05-05
  • C++算法學(xué)習(xí)之分支限界法的應(yīng)用

    C++算法學(xué)習(xí)之分支限界法的應(yīng)用

    分支限界法常以廣度優(yōu)先或以最小耗費(fèi)(最大效益)優(yōu)先的方式搜索問(wèn)題的解空間樹(shù)。本文將詳細(xì)講解分支限界法的應(yīng)用,需要的可以參考一下
    2022-05-05

最新評(píng)論

松江区| 周宁县| 柘荣县| 镇原县| 剑阁县| 德昌县| 濮阳市| 阳城县| 侯马市| 高尔夫| 元阳县| 公安县| 锦州市| 梓潼县| 托克托县| 文化| 沙坪坝区| 张北县| 白水县| 滕州市| 乌拉特前旗| 黄浦区| 大英县| 德令哈市| 平阳县| 巧家县| 阿勒泰市| 平阳县| 定陶县| 沙洋县| 镇宁| 五大连池市| 琼结县| 通道| 吉林省| 烟台市| 沙洋县| 台山市| 衡山县| 临沭县| 崇明县|