Связь между спецификаторами доступа и использованием списков инициализаторов для типов POD в C++0x

Принять два следующих класса:

class Test1{
 public:
  Test1()=default;
  Test1(char in1,char in2):char1(in1),char2(in2){}
  char char1;
  char char2;
};
class Test2{
 public:
  Test2()=default;
  Test2(char in1,char in2):char1(in1),char2(in2){}
 private:
  char char1;
  char char2;
};

Я знаю, что в C++0x оба этих класса рассматриваются как типы POD, и мы можем инициализировать их объекты, используя списки инициализаторов, как показано ниже:

Test1 obj1={'a','b'};//valid in c++0x
Test2 obj2={'a','b'};//valid in c++0x

Но мне интересно, какова техническая причина в том, что когда у нас есть разные спецификаторы доступа в классе, как показано ниже, невозможно использовать список инициализатора для инициализации объектов этого класса, и этот класс не рассматривается как тип POD?

class Test{
 public:
  Test()=default;
  Test(char in1,char in2):char1(in1),char2(in2){}
  char char1;
 private:
  char char2;
};
Test obj={'a','b'};//invalid in c++0x

Если вы не знаете определения POD в C++0x:
Класс / структура считается POD, если он является тривиальным, стандартным макетом и если все его нестатические члены являются POD.

Тривиальный класс или структура определяется как тот, который:

  1. Имеет тривиальный конструктор по умолчанию. Это может использовать синтаксис конструктора по умолчанию (SomeConstructor() = default;).
  2. Имеет тривиальный конструктор копирования, который может использовать синтаксис по умолчанию.
  3. Имеет тривиальный оператор назначения копирования, который может использовать синтаксис по умолчанию.
  4. Имеет тривиальный деструктор, который не должен быть виртуальным.

Класс или структура стандартного макета определяется как тот, который:

  1. Имеет только нестатические элементы данных, которые имеют тип стандартного макета
  2. Имеет одинаковый контроль доступа (открытый, закрытый, защищенный) для всех нестатических элементов.
  3. Не имеет виртуальных функций
  4. Не имеет виртуальных базовых классов
  5. Имеет только базовые классы стандартного типа
  6. Не имеет базовых классов того же типа, что и первый определенный нестатический член
  7. Либо не имеет базовых классов с нестатическими членами, либо не имеет нестатических элементов данных в наиболее производном классе и не более одного базового класса с нестатическими членами. По сути, в иерархии этого класса может быть только один класс, который имеет нестатические члены.

Если вы не знаете, что такое тривиальный конструктор или оператор:
Компилятор генерирует тривиальный элемент для каждого из следующих элементов класса, если он не объявлен пользователем: конструктор копирования, деструктор и оператор назначения копирования.
А также, если для класса нет объявленного пользователем конструктора, для этого класса создается простой конструктор по умолчанию, и в случае, если существуют конструкторы, объявленные пользователем, вы можете использовать синтаксис (SomeConstructor () = default;), чтобы сделать свой собственный тривиальный конструктор по умолчанию.

2 ответа

Решение
class Test{
 public:
  Test()=default;
  Test(char in1,char in2):char1(in1),char2(in2){}
  char char1;
 private:
  char char2;
};

учитывая вышеупомянутый класс, следующий синтаксис действителен в C++0x:

Test obj={'a','b'};//valid in c++0x

Окончательное предложение здесь.

"Техническая" причина заключается в следующем:

Нестатические члены данных (не объединяющего) класса с одинаковым контролем доступа распределяются так, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных с различным контролем доступа не определен (C++0x §9.2/12).

Пока все нестатические члены данных имеют одинаковый контроль доступа, их порядок четко определен; в противном случае их порядок не указан.

Другие вопросы по тегам