使用具有继承的结构的初始化列表

时间:2017-11-16 15:48:16

标签: c++ struct initialization visual-studio-2017 c++17

我有一个结构,我想使用初始化列表

进行初始化
struct Parent{};

struct Child : private Parent {
    int b;
};

int main() {
    Child c{ 1 };
    return 0;
}

查看其他问题,我发现this answer表明它应该可以在c ++ 17中使用。

然而,当我在VS2017中尝试上述代码段时,我得到了

Error   C2440   'initializing': cannot convert from 'initializer list' to 'child'

有没有办法利用这个新功能?

2 个答案:

答案 0 :(得分:8)

使用继承,聚合的每个基类子对象都像成员一样初始化。因此,为了聚合初始化,Child有两个子对象:Parenti。因此,在braced-init-list中需要两个初始值设定项:

Child c{ {}, 1 };

此外,为了使Child成为聚合,所有子对象必须 public 。所以你不能拥有私人基类。

当然,这假设Visual Studio正确实现了该功能。 VS2017 15.5不符合C ++ 17,但15.7支持此功能。

答案 1 :(得分:0)

引入了Extension to Aggregate Initialization(P0017R1),它在构造派生实例的同时仍显式初始化基类:

struct base { int a1, a2; };
struct derived : base { int b1; };

derived d1{{1, 2}, 3};      // full explicit initialization
derived d1{{}, 1};          // the base is value initialized

因此,使用“扩展集初始化初始化”,您将想要使用代码:Nicol Bolas's answer中再次提到的Child c{ {}, 1 }和他的警告,您需要使用public not private继承完全可以进行聚合初始化。

很遗憾,不支持P0017R1 until version 15.7。因此,可能需要升级Visual Studio来完成此任务。


如果这是不可能的,并且您无需多态性就可以解决问题,则可以临时定义:

struct Child {
    Parent a;
    int b;
};

您现在可以使用以下哪个一致的代码:Child c{ {}, 1 },并在升级到15.7后再回到继承时使用。