使用initializer-list初始化派生类的对象

时间:2015-03-17 09:11:50

标签: c++ c++11 initialization initializer-list

我的struct B来自struct A

struct A{
  int a;  
};

struct B : public A{
    int b;
};

有没有提供构造函数初始化B类型的对象的直接方法,假设使用初始化列表?

更多见解

我有两个struct用于在线程之间传递数据;第二个包含与第一个相同的数据,并添加了一些同步变量。我可以使第一个struct成为第二个struct的数据成员,或者只是复制第二个struct中的数据成员声明,​​以便轻松使用初始化列表;但我认为在这个特定的应用程序中,第二个{{1}}扩展第一个

在逻辑上更正确。

2 个答案:

答案 0 :(得分:3)

没有一个非常简洁的解决方案,但 至少是一个解决方案:

#include <type_traits>
#include <utility>

struct B : A
{
    int b;

    template <typename ...Args,
              typename = typename std::enable_if<
                             std::is_constructible<A, Args&&...>::value>
    B(int x, Args &&... args)
    : b(x), A(std::forward<Args>(args)...)
    { }
};

这个解决方案并不完全简短,但它很通用。 B的新构造函数仅存在于那些有意义的特化中,这要归功于enable-if SFINAE,因此B正是可以构造的。

这里还有一个我没有解决的危险,即新构造函数应该如何explicit。理想情况下,它应该与匹配的A构造函数一样明确,但这有点难以以编程方式检测(如N4064对对和元组所做的那样)。

答案 1 :(得分:0)

您不能对B使用聚合初始化,因为它不是聚合,根据[dcl.init.aggr] / 1:

  

聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或者   受保护的非静态数据成员(第11条),无基类(第10条),没有虚函数(10.3)。

更新:Kerrek SB使用模板构造函数提供了一个很好的解决方案,但是如果您愿意,可以为B添加非常简单的非模板构造函数:

struct B : public A{
    int b;
    B(const A& a_, int b_) : A(a_), b(b_) {}
};

并使用一对额外的括号:

B b {{3}, 5};