AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

理解C++之構造函數

來源: 責編: 時間:2023-11-28 17:12:18 281觀看
導讀相信做過Java、C++或者其他面向對象語言開發的朋友們一定對構造函數這個概念不陌生。以前初學C++的時候筆者看過幾次《C++ Primer》這本書,但是每次都是走馬觀花式的快速閱讀, 每次瀏覽完之后內心就會冒出兩個字:就這?現

相信做過Java、C++或者其他面向對象語言開發的朋友們一定對構造函數這個概念不陌生。以前初學C++的時候筆者看過幾次《C++ Primer》這本書,但是每次都是走馬觀花式的快速閱讀, 每次瀏覽完之后內心就會冒出兩個字:就這?現如今回想起來真是圖樣圖森破 。3NF28資訊網——每日最新資訊28at.com

學習最忌諱的就是心急如焚,砍柴不磨刀,所謂欲速則不達,一步一個腳印才能走得更穩。3NF28資訊網——每日最新資訊28at.com

3NF28資訊網——每日最新資訊28at.com

由問題開始

下面我們就從幾個問題出發,加深一下對C++中構造函數的了解:3NF28資訊網——每日最新資訊28at.com

1、構造函數初始化與賦值的問題

以下的這兩個寫法有什么區別?3NF28資訊網——每日最新資訊28at.com

class Person {public:    Person(const string name, int age);private:    string name;    int age;};// 第一種寫法Person::Person(const string name, int age) {    this->name = name;    this->age = age;}// 第二種寫法Person::Person(const string name, int age):name(name),age(age) {    }

在這個例子中第二種寫法是使用構造函數初始值的寫法,第一種寫法雖然合法,也沒有錯誤,但是并不是合理的寫法,并不推薦。3NF28資訊網——每日最新資訊28at.com

那么這兩種寫法有什么區別呢? 第一種寫法會經歷先初始化,再賦值這么兩個過程;而第二種寫法則是直接初始化數據成員一步到位。所以這里面會存在一個效率的問題,第二種寫法的效率更高。3NF28資訊網——每日最新資訊28at.com

我們再看一個例子,如果我們把類的成員使用const修飾呢,結果會怎樣?3NF28資訊網——每日最新資訊28at.com

class Person {public:    Person(const string name, int age);private:    string name;    const int age;};// 第一種寫法,編譯報錯Person::Person(const string name, int age) {    this->name = name;    this->age = age;}// 第二種寫法Person::Person(const string name, int age):name(name),age(age) {}

我們發現第一種寫法行不通了,不能編譯通過了,這是因為age被const修飾了,必須在初始化時賦值,所以第一種寫法就不行了,由此看出使用構造函數初始值的寫法更加規范,更加安全。3NF28資訊網——每日最新資訊28at.com

建議:在《Effective C++》一書中的第4條"確定對象被使用前已先被初始化"中也強調了絕對必要使用構造函數初始值3NF28資訊網——每日最新資訊28at.com

2、成員變量的初始化順序

如下例子,如果外部調用Point對象的getX方法,能拿到正確的值嗎?答案是不能的,因為成員x比成員y先初始化。3NF28資訊網——每日最新資訊28at.com

class Point {public:    Point(int x, int y);    int getX() const{        return x;    }    int getY() const{        return y;    }private:    int x;    int y;};// 本意是把 yVal的值賦值給成員變量y,然后把成員變量y的值賦值給成員變量xPoint::Point(int xVal, int yVal):y(yVal),x(y) {}

一般按照我們常規的思維,我們在構造函數中先寫了y,再x,那應該是寫初始化y,再初始化x吧?然而事實并不是這樣子的。3NF28資訊網——每日最新資訊28at.com

起始構造函數初始值是有一定的規則的:3NF28資訊網——每日最新資訊28at.com

構造函數初始值列表只說明用于初始化成員的值,而不限定初始化的具體執行順序。成員的初始化順序與它們在類定義中的出現順序一致:第一個成員先被初始化, 然后第二個,以此類推。構造函數初始值列表中初始值的前后位置關系不會影響實際的初始化順序。3NF28資訊網——每日最新資訊28at.com

3NF28資訊網——每日最新資訊28at.com

所以上面構造函數的寫法中雖然y出現在了x的前面,但是在成員變量聲明的時候是先聲明了x的,所以初始化的時候是先初始化了x,但是把一個未經初始化的y賦值給了x,那肯定是不能成功賦值的, 所以通過getX方法獲取到的值也就不是你想要的那個值了。3NF28資訊網——每日最新資訊28at.com

3、對于繼承而來的派生類的成員初始化順序是怎么樣的呢?

盡管在派生類對象中含有從基類繼承而來的成員,但是派生類并不能直接初始化這些成員。和其他創建了基類對象的代碼一樣,派生類也必須使用基類的構造函數來初始化它的基類部分。 首先初始化基類的部分,然后按照聲明的順序依次初始化派生類的成員。3NF28資訊網——每日最新資訊28at.com

3NF28資訊網——每日最新資訊28at.com

3、委托構造函數的執行順序

所謂委托構造函數就是構造函數相互調用。3NF28資訊網——每日最新資訊28at.com

當一個構造函數委托給另一個構造函數時,受委托的構造函數的初始值列表和函數體被依次執行。 如果受委托的構造函數體恰好是空的。假如函數體包含有代碼的話,將先執行這些代碼,然后控制權才會交還給委托者的函數體。3NF28資訊網——每日最新資訊28at.com

3NF28資訊網——每日最新資訊28at.com

4、構造函數異常如何捕獲

處理構造函數初始值異常的唯一方法是將構造函數寫成函數try語句塊。3NF28資訊網——每日最新資訊28at.com

5、如何讓類不能在棧內構造

筆者查了下網上的資料說大概就是說將構造方法私有化,并且將拷貝構造函數私有化就能禁止類的對象在棧內構造了。筆者測試了一下其實這并不嚴謹,這樣的做法只能做到在類的外部禁用了棧內初始化, 在類的內部依然可以使用棧的方式構造對象,比如一下例子:3NF28資訊網——每日最新資訊28at.com

class Data {public:// 在類的內部依然可以使用棧的方式構造    Data create() {        Data data = Data();    }private:    Data();    Data(const Data &data) {    }};

經過筆者的測試,私有化構造函數,再加上使用delete關鍵字移除拷貝構造函數即可實現禁用類在棧內構造的功能:3NF28資訊網——每日最新資訊28at.com

class Data {public:    // 不能在棧內構造,編譯會報錯    Data create() {        return Data();    }private:    Data();    Data(const Data &data) = delete;};

但是這種做法實在是太過了,而且筆者筆者才疏學淺,也不知道這種做法會不會造成什么隱藏的坑,如有高手,請賜教。3NF28資訊網——每日最新資訊28at.com

《More EffectiveC++》一書中第27條:要求(或禁止)對象產生與heap之中,提到將構造函數和析構函數私有化即可達到禁止對象在棧內定義的目的。 但是這個做法太過了,比較好的辦法是讓析構函數r成為 private,而構造函數仍為 public。3NF28資訊網——每日最新資訊28at.com

3NF28資訊網——每日最新資訊28at.com

6、如何讓類不能在堆內構造對象

使用new在堆內構造對象主要會調用構造函數以及new運算符這兩個步驟,所以我們只要把運算符new移除即可:3NF28資訊網——每日最新資訊28at.com

class Data {public:    Data();    // 重載new運算符,禁止使用new在堆內構造對象    void* operator new (size_t size) = delete;};

然而筆者發現,雖然這樣能夠禁用new在堆內構造對象,但是我們知道使用 malloc 也能在堆內分配對象,只是使用 malloc 不會調用類的構造函數而已,所以類內的所有成員都需要自己手動初始化, 那么有沒有辦法把malloc也禁用掉呢?筆者并不知曉,懇請高手賜教。。。3NF28資訊網——每日最新資訊28at.com

在《Effective C++》一書中第06條有提到為駁回編譯器自動(暗自)提供的機能,可將相應的成員函數聲明為private并且不予實現。3NF28資訊網——每日最新資訊28at.com

所以為了達到某個類只能在堆內或者只能在棧內構造的目的可以參考這一條。3NF28資訊網——每日最新資訊28at.com

總結一下

  • 誰先聲明誰先初始化,與構造函數中出現的順序無關;
  • 初始化值中的相關調用比構造函數中的函數體優先執行;
  • 在派生類中首先初始化基類的部分,然后按照聲明的順序依次初始化派生類的成員。

本文鏈接:http://www.tebozhan.com/showinfo-26-34928-0.html理解C++之構造函數

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 孩子喜歡飛機,于是我給她做了一個雷達

下一篇: Go 中切片(Slice)的長度與容量

標簽:
  • 熱門焦點
Top