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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

所以:無虛不基

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

改法為:將A類的xxx改為non-vritual,在派生類的構(gòu)造函數(shù)傳遞必要信息給基類的構(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)造期間,令派生類將必要的構(gòu)造信息向上傳遞給基類的構(gòu)造函數(shù)。

令operator=返回一個reference to *this

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

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

在operator=中處理自我賦值

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

px和py都指向一個對象,則是一個自我賦值。

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

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

避免方法:

1、證同測試

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

2、調(diào)整語序

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指向的一個副本,完成賦值
    delete p;//刪除原來的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ù)制對象時別忘了每個成分

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

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

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

編寫copy函數(shù)時:

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

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

且不要嘗試以某個copy函數(shù)實現(xiàn)另一個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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實現(xiàn)24位彩色圖像二值化

    C語言實現(xiàn)24位彩色圖像二值化

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)24位彩色圖像二值化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言選擇、循環(huán)、函數(shù)、數(shù)組與操作符

    C語言選擇、循環(huán)、函數(shù)、數(shù)組與操作符

    這篇文章主要介紹了C語言選擇、循環(huán)、函數(shù)、數(shù)組與操作符,文章基于C語言展開對主題的詳細(xì)介紹,下文內(nèi)容需要的小伙伴可以參考一下
    2022-04-04
  • C++中的繼承方式與菱形繼承解析

    C++中的繼承方式與菱形繼承解析

    這篇文章主要介紹了C++中的繼承方式與菱形繼承解析,繼承是類和類之間的關(guān)系,是代碼復(fù)用的重要手段,允許在保持原有類結(jié)構(gòu)的基礎(chǔ)上進(jìn)行擴(kuò)展,創(chuàng)建的新類與原有的類類似,只是多了幾個成員變量和成員函數(shù),需要的朋友可以參考下
    2023-08-08
  • C語言實現(xiàn)電器銷售管理系統(tǒng)

    C語言實現(xiàn)電器銷售管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)電器銷售管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++ explicit關(guān)鍵字講解

    C++ explicit關(guān)鍵字講解

    這篇文章主要介紹了C++ explicit關(guān)鍵字講解,++提供了explicit關(guān)鍵字,相對于implicit而言,他默認(rèn)關(guān)閉了隱式類型轉(zhuǎn)換方法。至于兩者有什么區(qū)別,看下面文章內(nèi)容的介紹吧
    2021-12-12
  • C++實現(xiàn)校園運(yùn)動會報名系統(tǒng)

    C++實現(xiàn)校園運(yùn)動會報名系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)校園運(yùn)動會報名系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • 深入剖析C語言中qsort函數(shù)的實現(xiàn)原理

    深入剖析C語言中qsort函數(shù)的實現(xiàn)原理

    這篇文章主要介紹了C語言中qsort函數(shù)的實現(xiàn)原理,本文將從回調(diào)函數(shù),qsort函數(shù)的應(yīng)用,qsort函數(shù)的實現(xiàn)原理三個方面進(jìn)行講解,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • 淺談CMake配置OpenCV 時靜態(tài)鏈接與動態(tài)鏈接的選擇

    淺談CMake配置OpenCV 時靜態(tài)鏈接與動態(tài)鏈接的選擇

    下面小編就為大家?guī)硪黄獪\談CMake配置OpenCV 時靜態(tài)鏈接與動態(tài)鏈接的選擇。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • C語言中的正則表達(dá)式使用示例詳解

    C語言中的正則表達(dá)式使用示例詳解

    正則表達(dá)式是使用單個字符串來描述、匹配一系列符合某個句法規(guī)則的字符串。本文通過示例代碼給大家介紹了C語言中的正則表達(dá)式使用,感興趣的朋友跟隨小編一起看看吧
    2019-07-07
  • C語言實現(xiàn)帶頭雙向循環(huán)鏈表的接口

    C語言實現(xiàn)帶頭雙向循環(huán)鏈表的接口

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)帶頭雙向循環(huán)鏈表的接口,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評論

勃利县| 柞水县| 湛江市| 南木林县| 凉城县| 锡林郭勒盟| 嵊州市| 阿拉善盟| 大宁县| 临潭县| 四子王旗| 页游| 清新县| 广昌县| 麦盖提县| 衡山县| 定边县| 公主岭市| 金湖县| 冕宁县| 景谷| 遂平县| 咸阳市| 香港 | 合肥市| 泾源县| 衡阳市| 武隆县| 东乡族自治县| 黑水县| 扎囊县| 大荔县| 阳曲县| 涟源市| 德保县| 奎屯市| 托克逊县| 大悟县| 彰武县| 大港区| 万州区|