maidamai
maidamai

Reputation: 722

Compose initialize class in c++

I'm not sure if this is called compose initialization.Basically what I want to know is:

Given the following code:

#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,%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", 2}, 1, 2, 3, "string", 3};
  foo1.print();
}

Upvotes: 2

Views: 108

Answers (1)

songyuanyao
songyuanyao

Reputation: 172984

This is aggregate initialization, Foo is an aggregate type.

Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

Given Foo foo1{{"base2", 2}, 1, 2, 3, "string", 3};, the subobject of Base is initialized from {"base2", 2} (it gets aggregate-initialized too), the data member mem_1 is initialized from 1, mem_2 is initialized from 2, mem_3 is initialized from 3, str_mem is initialized from "string" (by std::string's constructor taking const char*), class_mem is initialized from 3 (by the constructor Bar::Bar(int)).

Given Foo foo{{"base1", 2}, 1, 2, 3};, the preceding members are initialized in the same way as above, except that str_mem and class_mem are initialized from the empty list, as the result they're default-initialized (by their default constructors).

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) copy-initialized from empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates).

Upvotes: 3

Related Questions