日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++构造函数详解(转)

發(fā)布時(shí)間:2025/3/8 c/c++ 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++构造函数详解(转) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

c++構(gòu)造函數(shù)的知識在各種c++教材上已有介紹,不過初學(xué)者往往不太注意觀察和總結(jié)其中各種構(gòu)造函數(shù)的特點(diǎn)和用法,故在此我根據(jù)自己的c++編程經(jīng)驗(yàn)總結(jié)了一下c++中各種構(gòu)造函數(shù)的特點(diǎn),并附上例子,希望對初學(xué)者有所幫助。

??????????????????????????????????????? c++類的構(gòu)造函數(shù)詳解????????????????????????

一、 構(gòu)造函數(shù)是干什么的

class?Counter
{

public:
?????? ??// 類Counter的構(gòu)造函數(shù)
?????????// 特點(diǎn):以類名作為函數(shù)名,無返回類型
? ? ???? Counter()
?? ????? {
??????????????? m_value = 0;
???????? }
?????????
private:
??????
????? ???// 數(shù)據(jù)成員
? ? ? ???int?m_value;
}


?????? 該類對象被創(chuàng)建時(shí),編譯系統(tǒng)對象分配內(nèi)存空間,并自動調(diào)用該構(gòu)造函數(shù)->由構(gòu)造函數(shù)完成成員的初始化工作

eg:????Counter c1;
??????? 編譯系統(tǒng)為對象c1的每個(gè)數(shù)據(jù)成員(m_value)分配內(nèi)存空間,并調(diào)用構(gòu)造函數(shù)Counter( )自動地初始化對象c1的m_value值設(shè)置為0

故:

????????構(gòu)造函數(shù)的作用:初始化對象的數(shù)據(jù)成員。


二、 構(gòu)造函數(shù)的種類

class?Complex?
{?????????

private?:
????????double????m_real;
????????double????m_imag;

public:

????????//????無參數(shù)構(gòu)造函數(shù)
????????// 如果創(chuàng)建一個(gè)類你沒有寫任何構(gòu)造函數(shù),則系統(tǒng)會自動生成默認(rèn)的無參構(gòu)造函數(shù),函數(shù)為空,什么都不做
????????// 只要你寫了一個(gè)下面的某一種構(gòu)造函數(shù),系統(tǒng)就不會再自動生成這樣一個(gè)默認(rèn)的構(gòu)造函數(shù),如果希望有一個(gè)這樣的無參構(gòu)造函數(shù),則需要自己顯示地寫出來
??????? Complex(void)
? ? ? ? {
??????? ? ?? m_real = 0.0;
???????????? m_imag = 0.0;
? ? ? ? }?
????????
????????//????一般構(gòu)造函數(shù)(也稱重載構(gòu)造函數(shù))
????????// 一般構(gòu)造函數(shù)可以有各種參數(shù)形式,一個(gè)類可以有多個(gè)一般構(gòu)造函數(shù),前提是參數(shù)的個(gè)數(shù)或者類型不同(基于c++的重載函數(shù)原理)
????????// 例如:你還可以寫一個(gè) Complex( int num)的構(gòu)造函數(shù)出來
????????// 創(chuàng)建對象時(shí)根據(jù)傳入的參數(shù)不同調(diào)用不同的構(gòu)造函數(shù)
? ? ? ? Complex(double?real,?double?imag)
??????? {
???? ? ?? ?? m_real = real;
??? ? ?? ??? m_imag = imag;?????????
? ? ? ?? }
????????
????????//????復(fù)制構(gòu)造函數(shù)(也稱為拷貝構(gòu)造函數(shù))
????????//????復(fù)制構(gòu)造函數(shù)參數(shù)為類對象本身的引用,用于根據(jù)一個(gè)已存在的對象復(fù)制出一個(gè)新的該類的對象,一般在函數(shù)中會將已存在對象的數(shù)據(jù)成員的值復(fù)制一份到新創(chuàng)建的對象中
????????//????若沒有顯示的寫復(fù)制構(gòu)造函數(shù),則系統(tǒng)會默認(rèn)創(chuàng)建一個(gè)復(fù)制構(gòu)造函數(shù),但當(dāng)類中有指針成員時(shí),由系統(tǒng)默認(rèn)創(chuàng)建該復(fù)制構(gòu)造函數(shù)會存在風(fēng)險(xiǎn),具體原因請查詢 有關(guān) “淺拷貝” 、“深拷貝”的文章論述
??????? Complex(const?Complex & c)
??????? {
????????????????// 將對象c中的數(shù)據(jù)成員值復(fù)制過來
??????????????? m_real = c.m_real;
??????????????? m_img????= c.m_img;
??????? }????????????
????
????????// 類型轉(zhuǎn)換構(gòu)造函數(shù),根據(jù)一個(gè)指定的類型的對象創(chuàng)建一個(gè)本類的對象
????????// 例如:下面將根據(jù)一個(gè)double類型的對象創(chuàng)建了一個(gè)Complex對象
??????? Complex::Complex(double?r)
??????? {
??????????????? m_real = r;
??????????????? m_imag = 0.0;
??????? }

????????// 等號運(yùn)算符重載
????????// 注意,這個(gè)類似復(fù)制構(gòu)造函數(shù),將=右邊的本類對象的值復(fù)制給等號左邊的對象,它不屬于構(gòu)造函數(shù),等號左右兩邊的對象必須已經(jīng)被創(chuàng)建
????????// 若沒有顯示的寫=運(yùn)算符重載,則系統(tǒng)也會創(chuàng)建一個(gè)默認(rèn)的=運(yùn)算符重載,只做一些基本的拷貝工作
??????? Complex &operator=(?const?Complex &rhs )
??????? {
????????????????// 首先檢測等號右邊的是否就是左邊的對象本,若是本對象本身,則直接返回
????????????????if?(?this?== &rhs )?
??????????????? {
????????????????????????return?*this;
??????????????? }
????????????????
????????????????// 復(fù)制等號右邊的成員到左邊的對象中
????????????????this->m_real = rhs.m_real;
????????????????this->m_imag = rhs.m_imag;
????????????????
???????????????// 把等號左邊的對象再次傳出
???????????? ??// 目的是為了支持連等 eg:????a=b=c 系統(tǒng)首先運(yùn)行 b=c
?? ?? ?????????// 然后運(yùn)行 a= ( b=c的返回值,這里應(yīng)該是復(fù)制c值后的b對象)????
????????????????return?*this;
??????? }

};

下面使用上面定義的類對象來說明各個(gè)構(gòu)造函數(shù)的用法:

void?main()
{
????????// 調(diào)用了無參構(gòu)造函數(shù),數(shù)據(jù)成員初值被賦為0.0
? ? ? ? Complex c1,c2;

????????// 調(diào)用一般構(gòu)造函數(shù),數(shù)據(jù)成員初值被賦為指定值
??????? Complex c3(1.0,2.5);
????????// 也可以使用下面的形式
??????? Complex c3 = Complex(1.0,2.5);
????????
????????//????把c3的數(shù)據(jù)成員的值賦值給c1
????????//????由于c1已經(jīng)事先被創(chuàng)建,故此處不會調(diào)用任何構(gòu)造函數(shù)
????????//????只會調(diào)用 = 號運(yùn)算符重載函數(shù)
??????? c1 = c3;
????????
????????//????調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù)
????????//????系統(tǒng)首先調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù),將5.2創(chuàng)建為一個(gè)本類的臨時(shí)對象,然后調(diào)用等號運(yùn)算符重載,將該臨時(shí)對象賦值給c1
??????? c2 = 5.2;
????????
? ? ???// 調(diào)用拷貝構(gòu)造函數(shù)( 有下面兩種調(diào)用方式)?
??????? Complex c5(c2);
? ? ? ? Complex c4 = c2;??// 注意和 = 運(yùn)算符重載區(qū)分,這里等號左邊的對象不是事先已經(jīng)創(chuàng)建,故需要調(diào)用拷貝構(gòu)造函數(shù),參數(shù)為c2

????????
????????
}

三、思考與測驗(yàn)

1. 仔細(xì)觀察復(fù)制構(gòu)造函數(shù)

????????Complex(const?Complex & c)
??????? {
????????????????// 將對象c中的數(shù)據(jù)成員值復(fù)制過來
??????????????? m_real = c.m_real;
??????????????? m_img = c.m_img;
??????? }????
????????
為什么函數(shù)中可以直接訪問對象c的私有成員?

2. 挑戰(zhàn)題,了解引用與傳值的區(qū)別

??Complex test1(const?Complex& c)
? {
? ? ? ? ??return?c;
? }
??
? Complex test2(const?Complex c)
? {
? ? ? ???return?c;
?? }
???
?? Complex test3()
?? {
??????????static?Complex c(1.0,5.0);
? ????????return?c;
?? }
??
? Complex& test4()
? {
?????????static?Complex c(1.0,5.0);
?????????return?c;
? }
??
??void?main()
? {
? ?? ?? Complex a,b;
????
? ?? ???// 下面函數(shù)執(zhí)行過程中各會調(diào)用幾次構(gòu)造函數(shù),調(diào)用的是什么構(gòu)造函數(shù)?
????
? ? ?? test1(a);
? ? ?? test2(a);
?????
? ? ?? b = test3();
? ? ?? b = test4();
?????
? ? ?? test2(1.2);
? ? ???// 下面這條語句會出錯(cuò)嗎?
? ? ?? test1(1.2);?????//test1( Complex(1.2 )) 呢?
? }
?
四、附錄(淺拷貝與深拷貝)
?
?????? 上面提到,如果沒有自定義復(fù)制構(gòu)造函數(shù),則系統(tǒng)會創(chuàng)建默認(rèn)的復(fù)制構(gòu)造函數(shù),但系統(tǒng)創(chuàng)建的默認(rèn)復(fù)制構(gòu)造函數(shù)只會執(zhí)行“淺拷貝”,即將被拷貝對象的數(shù)據(jù)成員的 值一一賦值給新創(chuàng)建的對象,若該類的數(shù)據(jù)成員中有指針成員,則會使得新的對象的指針?biāo)赶虻牡刂放c被拷貝對象的指針?biāo)赶虻牡刂废嗤?#xff0c;delete該指針 時(shí)則會導(dǎo)致兩次重復(fù)delete而出錯(cuò)。下面是示例:
?
【淺拷貝與深拷貝】
?
#include <iostream.h>
#include <string.h>
class?Person?
{
public?:
????????
????????// 構(gòu)造函數(shù)
??????? Person(char?* pN)
??????? {
? ? ? ? ?? ?? cout <<?"一般構(gòu)造函數(shù)被調(diào)用 !\n";
? ? ? ? ?? ?? m_pName =?new?char[strlen(pN) + 1];
? ? ? ? ? ? ??//在堆中開辟一個(gè)內(nèi)存塊存放pN所指的字符串
? ? ? ? ? ? ??if(m_pName != NULL)?
????????????? {
?????????????????//如果m_pName不是空指針,則把形參指針pN所指的字符串復(fù)制給它
? ? ? ? ? ? ? ???? strcpy(m_pName ,pN);
????????????? }
??????? }????????
????????
????????// 系統(tǒng)創(chuàng)建的默認(rèn)復(fù)制構(gòu)造函數(shù),只做位模式拷貝
??????? Person(Person & p)????
??????? {?
? ? ? ? ? ? ?? ???//使兩個(gè)字符串指針指向同一地址位置?????????
???????????????? m_pName = p.m_pName;?????????
? ? ? ? }
???
??????? ~Person( )
??????? {
? ? ? ? ? ?? ?? delete m_pName;
??????? }
????????
private?:

????????char?* m_pName;
};

void?main( )
{?
??????? Person man("lujun");
??????? Person woman(man);?
????????
????????// 結(jié)果導(dǎo)致?? man 和????woman 的指針都指向了同一個(gè)地址
????????
????????// 函數(shù)結(jié)束析構(gòu)時(shí)
????????// 同一個(gè)地址被delete兩次
}


// 下面自己設(shè)計(jì)復(fù)制構(gòu)造函數(shù),實(shí)現(xiàn)“深拷貝”,即不讓指針指向同一地址,而是重新申請一塊內(nèi)存給新的對象的指針數(shù)據(jù)成員
Person(Person & chs);
{
? ? ? ???// 用運(yùn)算符new為新對象的指針數(shù)據(jù)成員分配空間
?? ? ? ? m_pName=new?char[strlen(p.m_pName)+ 1];

??? ? ???if(m_pName)?????????
? ?? ??? {
? ? ?? ????? ? ??// 復(fù)制內(nèi)容
? ? ? ????? ? ? strcpy(m_pName ,chs.m_pName);
? ?? ??? }
??????
? ? ????// 則新創(chuàng)建的對象的m_pName與原對象chs的m_pName不再指向同一地址了
}

轉(zhuǎn)載于:https://www.cnblogs.com/CloudPing/p/3705730.html

總結(jié)

以上是生活随笔為你收集整理的c++构造函数详解(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。