欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++構(gòu)造析構(gòu)賦值運(yùn)算函數(shù)應(yīng)用詳解

 更新時(shí)間:2022年09月24日 14:25:29   作者:RolleX  
構(gòu)造函數(shù)主要作用在于創(chuàng)建對(duì)象時(shí)為對(duì)象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動(dòng)調(diào)用,無(wú)須手動(dòng)調(diào)用;析構(gòu)函數(shù)主要作用在于對(duì)象銷(xiāo)毀前系統(tǒng)自動(dòng)調(diào)用,執(zhí)行一 些清理工作

了解C++默默編寫(xiě)哪些函數(shù)

當(dāng)實(shí)現(xiàn)一個(gè)空類(lèi),c++會(huì)為你補(bǔ)上構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),拷貝賦值運(yùn)算符,析構(gòu)函數(shù)

class Empty{};
//等于你寫(xiě)了
class{
public:
    Empty(){...};
    Empty(const Empty& rhs){...};
    ~Empty(){...};
    Empty& operator=(const Empty& rhs){...}
};

當(dāng)這些函數(shù)被調(diào)用是,才會(huì)被編譯器創(chuàng)建出來(lái)。如果你自己聲明了一個(gè)構(gòu)造函數(shù),編譯器將不會(huì)創(chuàng)建默認(rèn)構(gòu)造函數(shù)。

當(dāng)然,編譯器有時(shí)會(huì)拒絕生成operator=

class A{
public:
    NameObject{string& name};
private:
    string& nameValue;//為一個(gè)字符串引用
}
string newDog("peter");
string oldDog("fx")
A a(newDog);
A b(olddog);
a=b;//此處賦值就會(huì)導(dǎo)致a的nameValue綁定到不同對(duì)對(duì)象上面 而引用一旦綁定無(wú)法更改 是錯(cuò)誤的

所以如果打算在一個(gè)含有引用成員的class中支持賦值操作,必須要自己定義operator=()

不想使用編譯器函數(shù)

若不想使用編譯器自動(dòng)生成的函數(shù),就該明確拒絕

如果一個(gè)類(lèi)你想讓它是獨(dú)一無(wú)二,無(wú)法被拷貝的,則需要拒絕編譯器生成的copy構(gòu)造函數(shù)和copy賦值運(yùn)算符。

方法一:將copy構(gòu)造函數(shù)和copy賦值運(yùn)算符函數(shù)聲明為private并且故意不實(shí)現(xiàn)

class A{
public:
    ...
private:
    A(const A&);
    A& operator=(const A&);//只聲明不實(shí)現(xiàn)
}

因?yàn)樗芯幾g器生成的版本都是public。聲明一個(gè)成員函數(shù),阻止了編譯器自己創(chuàng)建它,而聲明為private,又可以阻止別人調(diào)用它。

客戶(hù)試圖拷貝A對(duì)象時(shí),編譯器會(huì)阻止,而當(dāng)在member或friend函數(shù)之內(nèi)調(diào)用時(shí),連接器阻止.

方法二:寫(xiě)一個(gè)父類(lèi),將copy構(gòu)造函數(shù)和copy賦值運(yùn)算符函數(shù)聲明為private并且故意不實(shí)現(xiàn),再繼承這個(gè)父類(lèi)。

class A{
protected:
    A(){}
    ~A(){}
private:
    A(const A&);
    A& operator=(const A&)
}

為多態(tài)基類(lèi)聲明virtual析構(gòu)函數(shù)

我的理解是:如果不這樣做,在delete父類(lèi)的指針的時(shí)候無(wú)法使用多態(tài)性質(zhì),只會(huì)刪除掉父類(lèi)的部分,而子類(lèi)的部分會(huì)無(wú)法刪除,造成局部銷(xiāo)毀。

class A{
public:
    A();
    ~A();
};
class B:public A{};
//如果設(shè)計(jì)一個(gè)函數(shù) 返回一個(gè)基類(lèi)的指針 可以使用多態(tài) 來(lái)自動(dòng)判斷是調(diào)用A還是B的析構(gòu)來(lái)刪除對(duì)象
A* base_pointer=getPointer();
delete base_pointer;
//當(dāng)子類(lèi)用一個(gè)指向父類(lèi)的指針來(lái)執(zhí)行刪除,若父類(lèi)的析構(gòu)函數(shù)不是virtual,則無(wú)法調(diào)用子類(lèi)的析構(gòu)函數(shù)
//導(dǎo)致只刪除 子類(lèi)中父類(lèi)的部分 剩下子類(lèi)獨(dú)有的部分

所以:無(wú)虛不基

base class的析構(gòu)函數(shù)一定得是vritual,且可以推廣到其他函數(shù),若一個(gè)class里面沒(méi)有一個(gè)virtual函數(shù),那它不適合當(dāng)一個(gè)base class。

class A{
public:
    A();
    virtual ~A();//應(yīng)該這么搞
};
class B:public A{};
//如果設(shè)計(jì)一個(gè)函數(shù) 返回一個(gè)基類(lèi)的指針 可以使用多態(tài) 來(lái)自動(dòng)判斷是調(diào)用A還是B的析構(gòu)來(lái)刪除對(duì)象
A* base_pointer=getPointer();
delete base_pointer;

但是,析構(gòu)函數(shù)不能無(wú)端聲明為virtual,因?yàn)槁暶鳛関irtual需要虛表指針(vptr),vptr也是要占內(nèi)存的,會(huì)增加對(duì)象的體積,減緩運(yùn)行速度。

所以:當(dāng)class至少含有一個(gè)virtual函數(shù),才為它聲明vritual虛構(gòu)函數(shù)

當(dāng)然,也可以將虛構(gòu)函數(shù)聲明為純虛函數(shù),使該class成為一個(gè)抽象基類(lèi),注意:必須為這個(gè)純虛函數(shù)提供一份定義。因?yàn)槲鰳?gòu)函數(shù)是從派生類(lèi)開(kāi)始往基類(lèi)調(diào)用,所以編譯器會(huì)在A(yíng)的派生類(lèi)的析構(gòu)函數(shù)中調(diào)用~A()。

class A{
public:
    virtual~ A()=0;
}
A::~A(){}//必須為這個(gè)純虛函數(shù)提供一份定義

別讓異常逃離析構(gòu)函數(shù)

C++不喜歡析構(gòu)函數(shù)出現(xiàn)異常。

可以在發(fā)生異常時(shí)終止程序,也可以吞下發(fā)生的異常

A::~A()
{
    try{ a.close();}
    catch(...){
        ...
        //制作運(yùn)轉(zhuǎn)記錄,記錄下close的失敗
        std::abort();//終止程序
    }
}
A::~A()
{
    try{ a.close();}
    catch(...){
        ...
       //記錄下close的調(diào)用失敗
    }
}

如果某個(gè)操作可能在失敗時(shí)拋出異常,而又必須要處理這個(gè)異常,這個(gè)異常必須來(lái)自析構(gòu)以外的函數(shù)。(這里其實(shí)不太理解,文中給的例子是用一個(gè)新的成員函數(shù)來(lái)直行關(guān)閉)

絕不在構(gòu)造和析構(gòu)過(guò)程中調(diào)用virtual函數(shù)

我的理解是:在構(gòu)造和析構(gòu)的過(guò)程中調(diào)用的virtual成員函數(shù)并沒(méi)有多態(tài)性質(zhì)(注意該虛函數(shù)不是指析構(gòu)函數(shù)和構(gòu)造函數(shù)是虛函數(shù),而是除此之外的一個(gè)成員函數(shù))

class A{
public:
    A();
    vritual void xxx() const =0;
};
A::A(){
    ...
    xxx();
}
class B:public A{
public:
    virtual xxx() const;
};
//當(dāng)執(zhí)行
B b;

派生類(lèi)的base class成分會(huì)在派生類(lèi)自身成分構(gòu)造之前先構(gòu)造,而A的構(gòu)造函數(shù)調(diào)用了虛函數(shù)xxx,這時(shí)xxx是A的xxx,而不會(huì)多態(tài)調(diào)用B的xxx,即使目前是在創(chuàng)建B對(duì)象。

根本原因是:在派生類(lèi)的基類(lèi)構(gòu)造期間,對(duì)象的類(lèi)型是基類(lèi)而不是派生類(lèi),只有當(dāng)派生類(lèi)自己的部分開(kāi)始執(zhí)行時(shí),該對(duì)象才變成一個(gè)派生類(lèi)。

該道理同樣用于析構(gòu)函數(shù)

改法為:將A類(lèi)的xxx改為non-vritual,在派生類(lèi)的構(gòu)造函數(shù)傳遞必要信息給基類(lèi)的構(gòu)造函數(shù)

class A{
public:
    A();
    void xxx() const =0;
};
A::A(){
    ...
    xxx();
};
class B:public A{
public:
    B(parameters):A(createXXX(parameters))
    {...}
private:
    static string createXXX(parameters);
};

在構(gòu)造期間,令派生類(lèi)將必要的構(gòu)造信息向上傳遞給基類(lèi)的構(gòu)造函數(shù)。

令operator=返回一個(gè)reference to *this

為了實(shí)現(xiàn)連鎖賦值,賦值操作符必須返回一個(gè)reference指向操作符的左側(cè),這是為class實(shí)現(xiàn)賦值操作符時(shí)必須遵守的協(xié)議。

//連鎖賦值
int x,y,z;
x=y=z=1;
class A{
public:
    A& operator=(const A& rhs)
    {
        return *this;
    }
}

在operator=中處理自我賦值

自我賦值發(fā)生在對(duì)象賦值給自己本身,例如*px=*py;

px和py都指向一個(gè)對(duì)象,則是一個(gè)自我賦值。

常發(fā)生在用引用賦值,指針賦值,多態(tài)等

可能會(huì)引發(fā)delete時(shí)將賦值和被賦值對(duì)象都刪除了

避免方法:

1、證同測(cè)試

A &A operator=(const A& rhs){
    if(this==&rhs) return *this;//一樣則什么也不做 直接返回
    ...
}

2、調(diào)整語(yǔ)序

class B{...};
class A{
private:
    B* pb;
}
A& A::operator=(const A& rhs){
    B* p=pb;//先記住原先的pb
    pb=new B(*rhs.pb);//令pb指向rhs.pb指向的一個(gè)副本,完成賦值
    delete p;//刪除原來(lái)的pb
    return *this;
}

3、使用copy and swap,不大推薦

class A{
    ...
    void swap(A &rhs);
    ...
}
A& A::operator=(const A& rhs){
    A temp(rhs);//拷貝rhs的副本
    swap(temp);//交換
    return *this;
}

復(fù)制對(duì)象時(shí)別忘了每個(gè)成分

如果自己定義了拷貝構(gòu)造函數(shù),編譯器將不會(huì)提醒你是否拷貝完所有成分,如果為class添加一個(gè)成員變量,則必須修改所有的copy函數(shù)和非標(biāo)準(zhǔn)形勢(shì)的operator=

給派生類(lèi)寫(xiě)copy函數(shù)的時(shí)候,也要復(fù)制它的基類(lèi)的成分,那些成分往往是private,所以要讓派生類(lèi)調(diào)用相應(yīng)的base class函數(shù)

B::B(const B &rhs):A(rhs),//調(diào)用基類(lèi)的copy構(gòu)造
...//對(duì)派生類(lèi)部分初始化
{}
B::operator=(const B& rhs){
    A::operator=(rhs);//對(duì)基類(lèi)部分賦值
    ...//對(duì)派生類(lèi)部分賦值
    return *this;
}

編寫(xiě)copy函數(shù)時(shí):

1、復(fù)制所有l(wèi)ocal成員變量

2、調(diào)用所有base classes內(nèi)的適當(dāng)copying函數(shù)

且不要嘗試以某個(gè)copy函數(shù)實(shí)現(xiàn)另一個(gè)copy函數(shù)

到此這篇關(guān)于C++構(gòu)造析構(gòu)賦值運(yùn)算函數(shù)應(yīng)用詳解的文章就介紹到這了,更多相關(guān)C++構(gòu)造析構(gòu)賦值運(yùn)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++去除輸入行中空白的方法

    C++去除輸入行中空白的方法

    這篇文章主要介紹了C++去除輸入行中空白的方法,涉及C++針對(duì)數(shù)組的遍歷與替換的相關(guān)使用技巧,需要的朋友可以參考下
    2015-07-07
  • C/C++?實(shí)現(xiàn)動(dòng)態(tài)資源文件釋放的方法

    C/C++?實(shí)現(xiàn)動(dòng)態(tài)資源文件釋放的方法

    當(dāng)我們開(kāi)發(fā)Windows應(yīng)用程序時(shí),通常會(huì)涉及到使用資源(Resource)的情況。資源可以包括圖標(biāo)、位圖、字符串等,它們以二進(jìn)制形式嵌入到可執(zhí)行文件中,這篇文章主要介紹了C/C++?實(shí)現(xiàn)動(dòng)態(tài)資源文件釋放,需要的朋友可以參考下
    2023-12-12
  • 美化你的代碼 vb(VBS)代碼格式化的實(shí)現(xiàn)代碼

    美化你的代碼 vb(VBS)代碼格式化的實(shí)現(xiàn)代碼

    雖然VB.NET出現(xiàn)很久了,但還有好多人仍然在使用VB6。我在實(shí)現(xiàn)一些小功能的時(shí)候也喜歡用VB6,畢竟誰(shuí)都不想每天的美好心情被VS那烏龜般的啟動(dòng)速度影響
    2012-05-05
  • C++獲取文件大小的4種常見(jiàn)技巧分享

    C++獲取文件大小的4種常見(jiàn)技巧分享

    這篇文章主要介紹了C++獲取文件大小的4種常見(jiàn)技巧分享,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • C語(yǔ)言宏函數(shù)container of()簡(jiǎn)介

    C語(yǔ)言宏函數(shù)container of()簡(jiǎn)介

    這篇文章介紹了C語(yǔ)言宏函數(shù)container of(),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Qt自定義控件實(shí)現(xiàn)進(jìn)度儀表盤(pán)

    Qt自定義控件實(shí)現(xiàn)進(jìn)度儀表盤(pán)

    這篇文章主要介紹了Qt自定義控件實(shí)現(xiàn)進(jìn)度儀表盤(pán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++中std::conditional的使用說(shuō)明

    C++中std::conditional的使用說(shuō)明

    這篇文章主要介紹了C++中std::conditional的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C語(yǔ)言中g(shù)etch()函數(shù)詳解及簡(jiǎn)單實(shí)例

    C語(yǔ)言中g(shù)etch()函數(shù)詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了C語(yǔ)言中g(shù)etch()函數(shù)詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • 淺談C++高并發(fā)場(chǎng)景下讀多寫(xiě)少的優(yōu)化方案

    淺談C++高并發(fā)場(chǎng)景下讀多寫(xiě)少的優(yōu)化方案

    本文主要介紹了淺談C++高并發(fā)場(chǎng)景下讀多寫(xiě)少的優(yōu)化方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Matlab利用垂距法實(shí)現(xiàn)提取離散坐標(biāo)數(shù)據(jù)特征點(diǎn)

    Matlab利用垂距法實(shí)現(xiàn)提取離散坐標(biāo)數(shù)據(jù)特征點(diǎn)

    垂距法是指根據(jù)中間頂點(diǎn)到其前、后兩相鄰頂點(diǎn)連線(xiàn)的距離的大小,來(lái)確定是否保留該頂點(diǎn)的一種線(xiàn)要素頂點(diǎn)壓縮算法。本文將利用這一算法實(shí)現(xiàn)提取離散坐標(biāo)數(shù)據(jù)特征點(diǎn),需要的可以參考下
    2022-04-04

最新評(píng)論