iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++聚合体初始化的方法是什么
  • 799
分享到

C++聚合体初始化的方法是什么

2023-07-05 02:07:56 799人浏览 安东尼
摘要

本篇内容介绍了“c++聚合体初始化的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!聚合体初始化(aggregate initial

本篇内容介绍了“c++聚合体初始化的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

聚合体初始化(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};

这样写将遵循嵌套聚合体初始化时的通用规则,你传递的实参被用来初始化哪一个成员取决于它们的顺序。

扩展聚合体初始化的动机

如果没有这个特性,那么所有的派生类都不能使用聚合体初始化,这意味着你要像下面这样定义构造函数:

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

现在我们不再需要定义任何构造函数就可以做到这一点。

我们可以直接使用嵌套花括号的语法来实现初始化,

如果给出了内层初始化需要的所有值就可以省略内层的花括号:

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

注意因为现在派生类也可以是聚合体,所以其他的一些初始化方法也可以使用:

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};};

或者,继续提供一个默认构造函数。

使用聚合体扩展

聚合体初始化的一个典型应用场景是对一个派生自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();

这里,内层花括号里的参数被传递给基类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"};

注意这不是通常的具有多态性的public继承,因为std::string没有虚成员函数,

你需要避免混淆这两种类型。

你甚至可以从多个基类和聚合体中派生出聚合体:

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

你可以像下面这样使用和初始化:

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

内部嵌套的初值列表将按照继承时基类声明的顺序传递给基类。

这个新的特性也可以帮助我们用很少的代码定义重载的lambda

聚合体的定义

总的来说,在C++17中满足如下条件之一的对象被认为是 聚合体 :

  • 是一个数组

  • 或者是一个满足如下条件的 类类型 (classstructuNIOn):

  • 没有用户定义的和explicit的构造函数

  • 没有使用using声明继承的构造函数

  • 没有privateprotected的非静态数据成员

  • 没有virtual函数

  • 没有virtual, private, protected的基类

然而,要想使用聚合体初始化来 初始化 聚合体,那么还需要满足如下额外的约束:

  • 基类中没有private或者protected的成员

  • 没有private或者protected的构造函数

下一节就有一个因为不满足这些额外约束导致编译失败的例子。

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起OKstd::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{};

会调用Derived隐式定义的默认构造函数,这个构造函数会调用基类Base的构造函数。

尽管基类的默认构造函数是private的,但在派生类的构造函数里调用它也是有效的,

因为派生类被声明为友元类。

自从C++17起,例子中的Derived是一个聚合体,所以它没有隐式的默认构造函数

(构造函数没有使用using声明继承)。因此,d1的初始化将是一个聚合体初始化,

如下表达式:

std::is_aggregate<Derived>::value

将返回true

然而,因为基类有一个private的构造函数(见上一节)所以不能使用花括号来初始化。

这和派生类是否是基类的友元无关。

“C++聚合体初始化的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: C++聚合体初始化的方法是什么

本文链接: https://www.lsjlt.com/news/349063.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++聚合体初始化的方法是什么
    本篇内容介绍了“C++聚合体初始化的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!聚合体初始化(aggregate initial...
    99+
    2023-07-05
  • C++聚合体初始化aggregateinitialization详细介绍
    目录聚合体初始化(aggregate initialization)扩展聚合体初始化的动机使用聚合体扩展聚合体的定义向后的不兼容性聚合体初始化(aggregate initializ...
    99+
    2023-02-03
    C++聚合体初始化 C++ aggregate initialization
  • c++数组初始化的方法是什么
    C++中有多种方式可以初始化数组:1. 使用赋值语句逐个初始化数组元素。```cppint arr[5];arr[0] = 1;ar...
    99+
    2023-09-28
    c++
  • c++指针数组初始化的方法是什么
    C++中,可以使用以下方法来初始化指针数组:1. 使用一维数组初始化指针数组:cppint arr[] = {1, 2, 3};in...
    99+
    2023-10-18
    c++
  • c语言数组初始化的方法是什么
    C语言中数组的初始化方法有多种,具体方法取决于数组的类型和使用场景。以下是常见的数组初始化方法:1. 逐个赋值初始化:逐个为数组的每...
    99+
    2023-10-10
    c语言
  • pycharm初始化的方法是什么
    PyCharm的初始化方法是通过安装并打开PyCharm,在首次打开时,会出现一个“Welcome to PyCharm”界面,用户...
    99+
    2023-09-13
    pycharm
  • linux初始化的方法是什么
    Linux的初始化方法可以通过执行以下步骤来完成:1. 启动计算机并进入BIOS设置,在启动选项中选择从可引导介质(如硬盘或USB驱...
    99+
    2023-08-30
    linux
  • ArrayList集合初始化及扩容方法是什么
    这篇文章主要介绍“ArrayList集合初始化及扩容方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ArrayList集合初始化及扩容方法是什么”文章能帮助大家解决问题。ArrayList集...
    99+
    2023-07-05
  • c语言char数组初始化的方法是什么
    在C语言中,有几种方法可以初始化char数组。 使用字符串字面量进行初始化: char str[] = "Hello"; 使...
    99+
    2023-10-23
    c语言
  • C#基类的初始化方法
    今天小编给大家分享一下C#基类的初始化方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。基类的初始化派生类继承了基类的成员变...
    99+
    2023-06-17
  • vue初始化data方法是什么
    今天小编给大家分享一下vue初始化data方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。vue初始化data方法有...
    99+
    2023-07-04
  • C语言指针数组初始化的方法是什么
    C语言中,指针数组的初始化可以通过以下两种方式实现:1. 逐个初始化:可以使用类似于普通数组的方式逐个为指针数组的元素赋值。例如:c...
    99+
    2023-10-18
    C语言
  • c语言数组初始化为0的方法是什么
    C语言数组初始化为0的方法有以下几种:1. 使用循环将每个元素赋值为0:```cint arr[10];for(int i = 0;...
    99+
    2023-10-08
    c语言
  • c语言二维数组初始化的方法是什么
    在C语言中,有多种方式可以初始化二维数组。1. 使用循环进行逐个赋值:```cint arr[3][3];int i, j;for(...
    99+
    2023-08-31
    c语言
  • golang数组初始化的方法是什么
    在Go语言中,可以使用以下方法初始化数组:1. 使用var关键字声明数组,并在声明时指定数组的长度,数组的元素会被自动初始化为对应类...
    99+
    2023-09-27
    golang
  • java变量的初始化方法是什么
    Java变量的初始化方法有以下几种:1. 声明变量时直接赋值:可以在声明变量时直接为其赋初值,例如:```javaint num =...
    99+
    2023-09-15
    java
  • spring中bean的初始化方法是什么
    在Spring中,bean的初始化可以通过两种方式来完成:使用@Bean注解的initMethod属性或者实现Initializin...
    99+
    2023-09-21
    spring
  • SpringBoot中的Bean初始化方法是什么
    本篇内容介绍了“SpringBoot中的Bean初始化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!注解说明使用注解: @Post...
    99+
    2023-06-21
  • android初始化页面的方法是什么
    在Android中,可以通过以下几种方法来初始化页面:1. 在Activity的onCreate()方法中进行初始化操作。onCre...
    99+
    2023-08-09
    android
  • delphi数组初始化的方法是什么
    在Delphi中,有几种初始化数组的方法:1. 手动初始化:可以通过逐个指定数组元素的值来手动初始化数组。例如:```delphiv...
    99+
    2023-09-22
    delphi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作