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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

子类初始化列表不能初始化父类元素 -- class 'Derived' does not have any field named 'x'

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 子类初始化列表不能初始化父类元素 -- class 'Derived' does not have any field named 'x' 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緣由

偶爾編寫如下代碼,編譯出錯,

class Base{ public:int x; };class Derived : public Base { public:Derived() : x(10) {cout << "Derived " << x << endl;};int y; };int main() {Base *p = new Derived(); }

錯誤:

D:\CLionProjects\Demo\main.cpp: In constructor ‘Derived::Derived()’:
D:\CLionProjects\Demo\main.cpp:45:17: error: class ‘Derived’ does not have any field named ‘x’
Derived() : x(10) {

錯誤是子類的構造方法的初始化列表中無法初始化父類成員變量。那么是為什么呢?本文從如下幾個方面進行思考討論?

  • 初始化列表為何物,為何要在初始化列表中初始化變量?
  • 初始化列表,構造函數的執行順序如何?
  • c++ 子類 父類的對象模型是如何的?
  • 初始化列表為何物,為何要在初始化列表中初始化變量?

    當我們定義變量時習慣于對其進行初始化,而非先定義,再賦值:

    string foo = "Hello World!"; // 定義并初始化 string bar; // 默認初始化為空string對象 bar = "Hello World!"; // 為bar賦一個新值。

    就對象的數據成員而言,初始化和賦值也有類似的區別,如果沒有在構造函數的初始化列表中顯示地初始化成員,則該成員將在構造函數體之前執行默認初始化,例如:

    class Demo { public:Demo(string name) { // 此處隱式的對name進行了初始化this->name = name; // 此處是賦值,并非初始化}; private:string name; };

    有很多地方強調要使用初始化列表進行變量的賦值,為何呢?個人匯總如下:

  • 效率問題,未使用初始化列表進行賦值,會調用默認構造方法(對于對象而言,對于進本變量則是賦初值)初始化,然后再使用operator=進行賦值。
  • 有些變量沒有默認的構造方法,比如自定義的類(顯示的定義了構造方法)。
  • 有些變量只能在初始化時賦值,不在再更改,比如const變量。
  • 引用變量只能在初始化時賦值。
  • 初始化列表,構造函數的執行順序如何?

    正如上面所述,初始化列表是在構造函數體之前執行:

    struct P {P(){cout << "P construct" << endl;}; }; class Base { public:Base():p(P()){cout << "Base construct" << endl;};P p; };int main() {Base p; }

    運行結果:

    P construct
    Base construct

    執行順序:父類初始化列表-> 父類構造函數->子類初始化列表->子類構造函數。

    c++ 子類 父類的對象模型是如何的?

    class Base { public:int x; };class Derived :: Base { public:int y; };int main() {Base *base = new Derived(); }

    總結

    猜測可能是如下原因:

  • 子類的初始化列表,只能對子類的成員變量進行初始化,也就是Derived::x(自己類的作用域),所以報子類無該變量的錯誤。
  • 因為首先調用了父類的默認構造方法,在這之前,執行父類的初始化列表對x進行了初始化,如果子類還可以對x進行初始化,那么就會對x進行兩次初始化;編譯器不允許行為;
  • 個人傾向于編譯行為,不能再子類的初始化列表顯示的父類的成員變量進行初始化;如果需要,在初始化列表中包含父類的相應構造方法(含有初始化列表)。

    總結

    以上是生活随笔為你收集整理的子类初始化列表不能初始化父类元素 -- class 'Derived' does not have any field named 'x'的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。