2013-11-07 5 views
5

Что происходит с тем, что совокупный общедоступный базовый класс (или даже несколько совокупных общедоступных базовых классов) приведет к тому, что класс потеряет хорошие свойства агрегатных классов?Почему базовый класс дисквалифицирует класс от агрегата?

Определение «совокупного базового класса» от http://en.cppreference.com/w/cpp/language/aggregate_initialization http://en.wikipedia.org/wiki/C++_classes#Aggregate_classes


Хорошие свойства агрегированных классов:

  • Без определения конструктора, агрегат типа может быть инициализирован путем передачи список значений, заключенный в фигурные скобки, для инициализации его членов (или базовых классов, если они позволили им).
  • Совокупные типы считаются «простыми» (обобщение PODs) и могут использоваться в качестве литературного типа для целей constexprs.

Сокращенный пример инициализации из http://en.cppreference.com/w/cpp/language/aggregate_initialization#Example:

#include <string> 
#include <array> 
struct S { 
    int x; 
    struct Foo { 
    int i; 
    int j; 
    int a[3]; 
    } b; 
}; 

int main() 
{ 
    S s1 = { 1, { 2, 3, {4, 5, 6} } }; 
    S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision 
} 

Смотрите также: What are Aggregates and PODs and how/why are they special?

+0

Я предполагаю, что это потому, что вы не сможете инициализировать элементы такого агрегата, используя список инициализаторов. – Praetorian

+2

Какие «приятные свойства» в частности вас беспокоят? Перечислите их, дайте примеры того, как они должны работать с пустым и непустым базовым классом и виртуальным наследованием, и к тому времени, когда вы это сделаете, у вас будет ваш ответ. Или еще гораздо лучший вопрос. –

+0

Итак, теперь, кажется, ваше высказывание все, что вам действительно нужно, - это написать один менее конструктор, конструктор, который, вероятно, будет только одной строкой. – aaronman

ответ

1

Это определение совокупности с C++ 11 стандарта, что на самом деле все, что я могу дают, не пытаясь угадать, что думал комитет, когда они приняли это решение.

1 Агрегат представляет собой массив или класс (пункт 9) без каких-либо предоставленного пользователя конструкторов (12.1), без каких-либо скрепляющих или равнополочного-инициализаторов для нестатических элементов данных (9.2), не частными или защищенные нестатические элементы данных (раздел 11), нет базовых классов (раздел 10) и нет виртуальных функций (10.3).

Жирным шрифтом сказано, что агрегат не имеет базовых классов.

Что касается проблемы с наследованием, которую вызывает другой ответ, вы можете сделать единую работу по инициализации с наследованием. ПРИМЕЧАНИЕ. A все еще является совокупностью.

struct A {                   
    int val_A;                               
};                     

struct B : public A {                
    int val_B;                  
    B(int a, int b) : A{a}, val_B(b) {}            
};                     
int main() {                  
    B b {2,3};                  
    return 0;                  
} 

Вы только что дали B конструктор, ИМО, стандарт мог бы так же легко выбрать его, как и по умолчанию. Агрегаты, вероятно, хранились, потому что они были в предыдущих стандартах, но правда в том, что C++ 11 вам действительно не нужны. На самом деле одна проблема заключается в том, что std::array нуждается в двойных скобках, так как у нее нет конструктора списка инициализаторов, я думаю, что эта проблема решается в C++ 14.

Я хотел бы добавить, что я не вижу, насколько агрегат добавляет к классу, учитывая новые возможности равномерной инициализации и списка инициализаторов.

+2

Он спрашивает, почему. – 0x499602D2

+1

Он спрашивает * почему * имеет базовый класс (который сам является агрегатом) приведет к тому, что класс перестанет быть агрегатом – Praetorian

+0

@Praetorian стандарт не должен принимать это решение, он ничего не говорит о том, почему. Я понимаю, что я не ответил на полный вопрос, но что еще я могу сказать? – aaronman

0

Как бы вы инициализировали базовый класс?

Derived d = {{1, 2}, 3, 4}; 

Или

Derived d = {1, 2, 3, 4}; 

Является

Derived d = {3, 4}; 

разрешается?

Чтобы избежать всего этого, нет базовых классов.

+0

за исключением того, что я уверен, что производный класс может использовать единый синтаксис инициализации, который заканчивается тем же – aaronman

+1

@aaronman: я уверен, что он не сможет, если вы не напишете конструктор, и в этом случае это будет контролировать порядок аргументов и сколько их передают базовому классу. –

+2

Предположим, что базовый класс был перемещен как первый элемент.Как бы вы инициализировали первый член агрегатного класса? Я бы сказал, что вопрос имеет тот же ответ. – leewz

1

Согласно http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3308.pdf

Несмотря на явные намерения стандарта типа В не буквальное тип:

struct A {}; struct B : A {}; 

Это происходит потому, что его конструктор не неявно определен пока он не odr- и до этого момента у него нет конструкторов constexpr.

Честно не уверен, что это означает, однако.

Смежные вопросы