9

我相信现代 C++ 初始化器列表对于初始化对象非常有用,以至于不再需要定义自己的构造函数:

struct point
{
    float coord[3];
};

point p = {1.f, 2.f, 3.f}; // nice !

但是,当我的类从另一个类继承时,这不起作用:

template<typename T>
class serializable
{
    protected:
        serializable() = default;
    ...
    // other stuff
}

struct point : public serializable<point>
{
    float coord[3];
};
point p = {1.f, 2.f, 3.f}; // Doesn't work :(

我尝试添加point() = default;到我的点课程,但这也不起作用。我怎样才能仍然用初始化列表初始化点?

4

1 回答 1

10

您的原始案例依赖于聚合初始化 [dcl.init.list]:

类型 T 的对象或引用的列表初始化定义如下:
...
— 否则,如果T是聚合,则执行聚合初始化

如果聚合和聚合初始化来自 [dcl.init.aggr],则强调我的:

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

当聚合由初始化列表初始化时,如 8.5.4 中所指定,初始化列表的元素被视为聚合成员的初始化,按递增的下标或成员顺序。每个成员都是从相应的初始化子句复制初始化的。

但是现在,既然point有了基类(serializable<point>),point就不再是聚合,也不再支持聚合初始化了。

解决方案是简单地提供这样一个构造函数来初始化point

struct point : public serializable<point>
{
    template <typename... T>
    point(T... ts) 
    : coord{ts...}
    { } 

    float coord[3];
};
于 2015-04-30T14:24:08.077 回答