为什么有一个基类会使一个类不合格?

时间:2013-11-07 21:13:51

标签: c++ c++11

使用聚合公共基类(甚至多个聚合公共基类)会使类失去聚合类的优良属性是什么意思?

"聚合基类的定义"从 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?

4 个答案:

答案 0 :(得分:3)

根据http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3308.pdf

  

尽管标准有明确的意图,但B类不是文字类型:

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

这是因为它的构造函数在使用odr之前不会被隐式定义,直到那时它没有constexpr构造函数。

老实说,不确定这意味着什么。

答案 1 :(得分:2)

这是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一个构造函数,IMO标准可以像默认一样轻松选择它。聚合物可能保留在原因中,因为它们符合以前的标准,但事实是c ++ 11的功能你真的不需要它们。实际上有一个问题是std::array需要双括号,因为它没有初始化列表构造函数,我认为这个问题在c ++ 14中得到解决。

我想补充一点,鉴于统一初始化和初始化列表的新功能,我没有看到聚合添加到类的程度。

答案 2 :(得分:2)

由于具有公共、非虚拟基类的 C++17 类可以聚合。

struct Base1 {
 int a, b;
};
struct Base2 {
 int c;
};

struct Foo : Base1, Base2 {
    int d, e;
};

struct Foo 的对象可以聚合初始化。以下初始化是等效的:

Foo foo {Base1{1, 2}, Base2{3}, 4, 5};
Foo foo {{1, 2}, {3}, 4, 5};
Foo foo {1, 2, 3, 4, 5};

答案 3 :(得分:0)

您如何初始化基类?

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

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

Derived d = {3, 4};

允许?

为了避免所有这一切,没有基类。