Связь между спецификаторами доступа и использованием списков инициализаторов для типов 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.
Тривиальный класс или структура определяется как тот, который:
- Имеет тривиальный конструктор по умолчанию. Это может использовать синтаксис конструктора по умолчанию (SomeConstructor() = default;).
- Имеет тривиальный конструктор копирования, который может использовать синтаксис по умолчанию.
- Имеет тривиальный оператор назначения копирования, который может использовать синтаксис по умолчанию.
- Имеет тривиальный деструктор, который не должен быть виртуальным.
Класс или структура стандартного макета определяется как тот, который:
- Имеет только нестатические элементы данных, которые имеют тип стандартного макета
- Имеет одинаковый контроль доступа (открытый, закрытый, защищенный) для всех нестатических элементов.
- Не имеет виртуальных функций
- Не имеет виртуальных базовых классов
- Имеет только базовые классы стандартного типа
- Не имеет базовых классов того же типа, что и первый определенный нестатический член
- Либо не имеет базовых классов с нестатическими членами, либо не имеет нестатических элементов данных в наиболее производном классе и не более одного базового класса с нестатическими членами. По сути, в иерархии этого класса может быть только один класс, который имеет нестатические члены.
Если вы не знаете, что такое тривиальный конструктор или оператор:
Компилятор генерирует тривиальный элемент для каждого из следующих элементов класса, если он не объявлен пользователем: конструктор копирования, деструктор и оператор назначения копирования.
А также, если для класса нет объявленного пользователем конструктора, для этого класса создается простой конструктор по умолчанию, и в случае, если существуют конструкторы, объявленные пользователем, вы можете использовать синтаксис (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).
Пока все нестатические члены данных имеют одинаковый контроль доступа, их порядок четко определен; в противном случае их порядок не указан.