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

C++聚合體初始化aggregate initialization詳細介紹

 更新時間:2023年02月03日 15:50:13   作者:另尋滄海  
這篇文章主要介紹了C++聚合體初始化aggregate initialization,C++有很多初始化對象的方法。其中之一叫做 聚合體初始化(aggregate initialization) ,這是聚合體專有的一種初始化方法

聚合體初始化(aggregate initialization)

C++有很多初始化對象的方法。其中之一叫做 聚合體初始化(aggregate initialization) ,這是聚合體專有的一種初始化方法。

從C語言引入的初始化方式是用花括號括起來的一組值來初始化類:

struct Data {
    std::string name;
    double value;
};
Data x = {"test1", 6.778};

自從C++11起,你可以忽略等號:

Data x{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"test1", 6.778};

自從C++17起,聚合體可以擁有基類。也就是說像下面這種從其他類派生出的子類也可以使用這種初始化方法:

struct MoreData : Data {
    bool done;
}
MoreData y{{"test1", 6.778}, false};

如你所見,聚合體初始化時可以用一個子聚合體初始化來初始化類中來自基類的成員。

另外,你甚至可以省略子聚合體初始化的花括號:

MoreData y{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"test1", 6.778, false};

這樣寫將遵循嵌套聚合體初始化時的通用規(guī)則,你傳遞的實參被用來初始化哪一個成員取決于它們的順序。

擴展聚合體初始化的動機

如果沒有這個特性,那么所有的派生類都不能使用聚合體初始化,這意味著你要像下面這樣定義構造函數(shù):

struct Cpp14Data : Data {
    bool done;
    Cpp14Data (const std::string& s, double d, bool b) : Data{s, d}, done {
    }
};
Cpp14Data y{"test1", 6.778, false};

現(xiàn)在我們不再需要定義任何構造函數(shù)就可以做到這一點。

我們可以直接使用嵌套花括號的語法來實現(xiàn)初始化,

如果給出了內(nèi)層初始化需要的所有值就可以省略內(nèi)層的花括號:

MoreData x{{"test1", 6.778}, false};    // 自從C++17起OK
MoreData y{"test1", 6.778, false};      // OK

注意因為現(xiàn)在派生類也可以是聚合體,所以其他的一些初始化方法也可以使用:

MoreData u;     // OOPS:value/done未初始化
MoreData z{};   // OK: value/done初始化為0/false

如果覺得這樣很危險,可以使用成員初始值:

struct Data {
    std::string name;
    double value{0.0};
};
struct Cpp14Data : Data {
    bool done{false};
};

或者,繼續(xù)提供一個默認構造函數(shù)。

使用聚合體擴展

聚合體初始化的一個典型應用場景是對一個派生自C風格結構體并且添加了新成員的類進行初始化。例如:

struct Data {
    const char* name;
    double value;
};
struct CppData : Data {
    bool critical;
    void print() const {
        std::cout << '[' << name << ',' << value << "]\n";
    }
};
CppData y{{"test1", 6.778}, false};
y.print();

這里,內(nèi)層花括號里的參數(shù)被傳遞給基類Data。

注意你可以跳過初始化某些值。在這種情況下,跳過的成員將會進行默認初始化

(基礎類型會被初始化為0false或者nullptr,類類型會默認構造)。

例如:

CppData x1{};           // 所有成員默認初始化為0值
CppData x2{{"msg"}}     // 和{{"msg", 0.0}, false}等價
CppData x3{{}, true};   // 和{{nullptr, 0.0}, true}等價
CppData x4;             // 成員的值未定義

注意使用空花括號和不使用花括號完全不同:

x1的定義會把所有成員默認初始化為0值,

因此字符指針name被初始化為nullptr

double類型的value初始化為0.0,

bool類型的flag初始化為falsex4的定義沒有初始化任何成員。所有成員的值都是未定義的。

你也可以從非聚合體派生出聚合體。例如:

struct MyString : std::string {
    void print() const {
        if (empty()) {
            std::cout << "<undefined>\n";
        }
        else {
            std::cout << c_str() << '\n';
        }
    }
};
MyString x{{"hello"}};
MyString y{"world"};

注意這不是通常的具有多態(tài)性的public繼承,因為std::string沒有虛成員函數(shù),

你需要避免混淆這兩種類型。

你甚至可以從多個基類和聚合體中派生出聚合體:

template<typename T>
struct D : std::string, std::complex<T>
{
    std::string data;
};

你可以像下面這樣使用和初始化:

D<float> s{{"hello"}, {4.5, 6.7}, "world"}; // 自從C++17起OK
D<float> t{"hello", {4.5, 6.7}, "world"};   // 自從C++17起OK
std::cout << s.data;                        // 輸出:"world"
std::cout << static_cast<std::string>(s);   // 輸出:"hello"
std::cout << static_cast<std::complex<float>>(s);   //輸出:(4.5,6.7)

內(nèi)部嵌套的初值列表將按照繼承時基類聲明的順序傳遞給基類。

這個新的特性也可以幫助我們用很少的代碼定義重載的lambda

聚合體的定義

總的來說,在C++17中滿足如下條件之一的對象被認為是 聚合體 :

  • 是一個數(shù)組
  • 或者是一個滿足如下條件的 類類型 (class、structunion):
  • 沒有用戶定義的和explicit的構造函數(shù)
  • 沒有使用using聲明繼承的構造函數(shù)
  • 沒有privateprotected的非靜態(tài)數(shù)據(jù)成員
  • 沒有virtual函數(shù)
  • 沒有virtual, private, protected的基類

然而,要想使用聚合體初始化來 初始化 聚合體,那么還需要滿足如下額外的約束:

  • 基類中沒有private或者protected的成員
  • 沒有private或者protected的構造函數(shù)

下一節(jié)就有一個因為不滿足這些額外約束導致編譯失敗的例子。

C++17引入了一個新的類型特征is_aggregate<>

來測試一個類型是否是聚合體:

template<typename T>
struct D : std::string, std::complex<T> {
    std::string data;
};
D<float> s{{"hello"}, {4.5, 6.7}, "world"};         // 自從C++17起OK
std::cout << std::is_aggregate<decltype(s)>::value; // 輸出1(true)

向后的不兼容性

注意下面的例子不能再通過編譯:

struct Derived;
struct Base {
    friend struct Derived;
private:
    Base() {
    }
};
struct Derived : Base {
};
int main()
{
    Derived d1{};   // 自從C++17起ERROR
    Derived d2;     // 仍然OK(但可能不會初始化)
}

在C++17之前,Derived不是聚合體。因此

Derived d1{};

會調(diào)用Derived隱式定義的默認構造函數(shù),這個構造函數(shù)會調(diào)用基類Base的構造函數(shù)。

盡管基類的默認構造函數(shù)是private的,但在派生類的構造函數(shù)里調(diào)用它也是有效的,

因為派生類被聲明為友元類。

自從C++17起,例子中的Derived是一個聚合體,所以它沒有隱式的默認構造函數(shù)

(構造函數(shù)沒有使用using聲明繼承)。因此,d1的初始化將是一個聚合體初始化,

如下表達式:

std::is_aggregate<Derived>::value

將返回true。

然而,因為基類有一個private的構造函數(shù)(見上一節(jié))所以不能使用花括號來初始化。

這和派生類是否是基類的友元無關。

到此這篇關于C++聚合體初始化aggregate initialization詳細介紹的文章就介紹到這了,更多相關C++聚合體初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言中的指針新手初階指南

    C語言中的指針新手初階指南

    指針是C語言的靈魂,精華之所在,指針強大而危險,用得好是一大利器,用得不好是一大潛在危害,下面這篇文章主要給大家介紹了C語言中指針的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • C++實現(xiàn)LeetCode(106.由中序和后序遍歷建立二叉樹)

    C++實現(xiàn)LeetCode(106.由中序和后序遍歷建立二叉樹)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(106.由中序和后序遍歷建立二叉樹),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 在Visual Studio中用C++語言創(chuàng)建DLL動態(tài)鏈接庫圖文教程

    在Visual Studio中用C++語言創(chuàng)建DLL動態(tài)鏈接庫圖文教程

    這篇文章主要介紹了在Visual Studio中用C++語言創(chuàng)建DLL動態(tài)鏈接庫圖文教程,本文詳細講解了DLL庫的創(chuàng)建過程,并給出了代碼示例,需要的朋友可以參考下
    2014-09-09
  • Qt sender()函數(shù)的具體使用

    Qt sender()函數(shù)的具體使用

    在處理信號時,Qt提供了一個特殊的函數(shù)sender(),可以返回發(fā)送信號的對象指針,以實現(xiàn)更靈活的代碼邏輯,本文就來介紹一下Qt sender()函數(shù)的具體使用,感興趣的可以了解一下
    2024-01-01
  • C++詳解如何實現(xiàn)兩個線程交替打印

    C++詳解如何實現(xiàn)兩個線程交替打印

    這篇文章主要介紹了使用C++庫實現(xiàn)兩個線程交替打印,一個線程打印奇數(shù)、一個線程打印偶數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 深入理解char *a與char a[]的區(qū)別

    深入理解char *a與char a[]的區(qū)別

    很多人可能或多或少知道char *a與char a[]的一些區(qū)別,但如果詳細的說出來卻不知如何說去,下面這篇文章就給大家詳細介紹了關于C語言中char *a與char a[]的區(qū)別,有需要的朋友們可以參考借鑒,下面來一起學習學習吧。
    2016-12-12
  • 詳解C++設計模式編程中責任鏈模式的應用

    詳解C++設計模式編程中責任鏈模式的應用

    這篇文章主要介紹了C++設計模式編程中責任鏈模式的應用,責任鏈模式使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關系,需要的朋友可以參考下
    2016-03-03
  • 使用C++一步步實現(xiàn)俄羅斯方塊

    使用C++一步步實現(xiàn)俄羅斯方塊

    本文給大家分享的是作者在使用C++制作俄羅斯方塊的時候的思路分析以及開發(fā)準備和實驗原理,都是些基礎的知識儲備,希望大家能夠喜歡,具體的代碼我們下一節(jié)再分享給大家
    2017-12-12
  • C語言三子棋一步步實現(xiàn)詳程

    C語言三子棋一步步實現(xiàn)詳程

    三子棋是一種民間傳統(tǒng)游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等。將正方形對角線連起來,相對兩邊依次擺上三個雙方棋子,只要將自己的三個棋子走成一條線,對方就算輸了,想用c語言做出這個游戲,事實上也是比較簡單的,下面通過c語言進行對五子棋的分析
    2022-02-02
  • C++變量,常量,數(shù)組和字符串詳解

    C++變量,常量,數(shù)組和字符串詳解

    這篇文章主要介紹了C++變量,常量,數(shù)組和字符串,是C++入門學習中的基礎知識,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-10-10

最新評論

赫章县| 青川县| 延吉市| 诸城市| 中超| 华安县| 武威市| 日照市| 吉隆县| 宜兴市| 永康市| 沅江市| 凤山县| 德格县| 灵台县| 开远市| 乌拉特中旗| 荆州市| 正蓝旗| 永济市| 聂拉木县| 八宿县| 会宁县| 中超| 康乐县| 紫云| 怀仁县| 平谷区| 千阳县| 库车县| 蒙山县| 怀化市| 福州市| 屯门区| 河源市| 庆元县| 遵化市| 阳春市| 南昌县| 开阳县| 岳西县|