为何含虚函数时聚合初始化无法生效?
为结构体引入虚函数后无法使用聚合初始化的解决方法
问题描述
给结构体添加虚函数(或继承含虚函数的结构体)后,无法再使用聚合初始化,报错:
error C2440: 'initializing': cannot convert from 'initializer list' to 'Point_3'
聚合初始化相比手动逐个成员赋值便捷得多:
A.x = 100; A.y = 100;
示例代码如下:
#include <iostream> struct Point_1 { int x; int y; void foo() { std::cout << "x: " << x << std::endl; std::cout << "y: " << y << std::endl; } }; struct Point_2 { int x; int y; virtual void foo() {} }; struct Point_3 : Point_2 { void foo() override { std::cout << "x: " << x << std::endl; std::cout << "y: " << y << std::endl; } }; int main() { Point_1 A = { 100, 100 }; A.foo(); Point_3 B = { {200, 200} }; // 报错位置 B.foo(); return 0; }
原因
C++标准明确规定:包含虚函数、虚基类,或继承非聚合类的类/结构体,不属于聚合类型,因此无法使用聚合初始化:
Point_1是普通结构体,属于聚合类型,支持聚合初始化;Point_2因包含虚函数,不再是聚合类型;Point_3继承自非聚合类型Point_2,自然也不属于聚合类型,所以原初始化方式会报错。
解决方案
1. 添加构造函数
为基类定义构造函数,派生类可继承该构造函数,用构造函数初始化替代聚合初始化:
struct Point_2 { int x; int y; virtual void foo() {} // 添加带参构造函数 Point_2(int x_val, int y_val) : x(x_val), y(y_val) {} }; struct Point_3 : Point_2 { using Point_2::Point_2; // 继承基类的构造函数 void foo() override { std::cout << "x: " << x << std::endl; std::cout << "y: " << y << std::endl; } }; // 初始化方式 Point_3 B(200, 200);
2. C++20及以上使用指定成员初始化
C++20放宽了非聚合类型的初始化规则,支持直接指定成员赋值:
// 仅适用于C++20及更高版本 Point_3 B = { .x = 200, .y = 200 };
3. 手动成员赋值(备选)
如果无法修改结构体定义,只能手动逐个赋值:
Point_3 B; B.x = 200; B.y = 200;
内容的提问来源于stack exchange,提问作者machine_1
相关产品推荐
相关产品推荐

