在C ++中编写初始化类

问题描述

我不确定是否将其称为compose initialization。基本上我想知道的是:

  • 如何初始化foo中的对象main
  • 这种初始化是否有一些规则,因为我发现有时会失败。

给出以下代码

#include <iostream>
#include <string>
#include <vector>

class Base {
public:
  std::string str_mem;
  int int_val = 0;
};

class Bar {
public:
  Bar() = default;
  Bar(int val) : int_val(val) {
  }

  auto GetVal() {
    return int_val;
  }

private:
  int int_val = 0;
};

class Foo : public Base {
public:
  int mem_1;
  int mem_2;
  int mem_3;

  std::string str_mem;
  Bar class_mem;

  auto print() {
    printf("[%d,%d,%s,%d]\n",mem_1,mem_2,mem_3,str_mem.c_str(),class_mem.GetVal());
  }
};

auto main(int argc,char** argv) -> int {
  Foo foo{{"base1",2},1,2,3}; // How `foo` is constructed,any constructor get called?
  foo.print();

  Foo foo1{{"base2",3,"string",3};
  foo1.print();
}

解决方法

这是aggregate initializationFooaggregate type

每个direct public base,(since C++17)数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,从初始化列表的相应子句中进行复制初始化。

鉴于Foo foo1{{"base2",2},1,2,3,"string",3};Base的子对象是从{"base2",2}初始化的(它也被聚合初始化),数据成员mem_1是从{{1}初始化的},1mem_2初始化,2mem_3初始化,3str_mem初始化(由"string"的构造函数采用std::string),const char*class_mem初始化(由构造函数3)。

鉴于Bar::Bar(int),前面的成员以与上述相同的方式初始化,除了Foo foo{{"base1",3};str_mem是从空列表中初始化的,因此它们是默认的-初始化(通过其默认构造函数)。

如果初始化程序子句的数量少于成员class_mem的数量,或者初始化程序列表完全为空,则其余成员and bases (since C++17)从空列表中复制and bases (since C++17),在遵循通常的列表初始化规则(该规则对具有默认构造函数的非类类型和非聚合类执行值初始化,并对聚合进行聚合初始化)。