访问修饰符为何影响列表初始化的构造函数匹配?私有成员类如何列表初始化?
C++私有成员类的列表初始化问题解答
问题背景
在C++中,拥有公有成员的类(如下例的Foo)可通过列表初始化正常创建对象,但仅包含私有成员的类(如下例的Bar)使用列表初始化时会触发编译错误,提示找不到匹配的构造函数。
代码示例
#include <string> class Foo { public: int a; std::string s; float f; }; class Bar { int a; std::string s; float f; }; int main() { Foo obj{0, "", 0.0f}; // Bar obj2{0, "", 0.0f}; // Error! return 0; }
编译错误信息
<source>: In function 'int main()': <source>:18:25: error: no matching function for call to 'Bar::Bar(<brace-enclosed initializer list>)' 18 | Bar obj2{0, "", 0.0f}; | ^ <source>:10:7: note: candidate: 'Bar::Bar()' 10 | class Bar { | ^~~ <source>:10:7: note: candidate expects 0 arguments, 3 provided <source>:10:7: note: candidate: 'Bar::Bar(const Bar&)' <source>:10:7: note: candidate expects 1 argument, 3 provided <source>:10:7: note: candidate: 'Bar::Bar(Bar&&)' <source>:10:7: note: candidate expects 1 argument, 3 provided
问题解答
1. 如何实现仅由私有变量组成的简单类的直接列表初始化?
最直接的方式是手动显式定义与成员变量匹配的构造函数,通过成员初始化列表完成私有成员的赋值:
class Bar { int a; std::string s; float f; public: Bar(int a_, std::string s_, float f_) : a(a_), s(std::move(s_)), f(f_) {} };
此时即可通过Bar obj2{0, "", 0.0f};直接完成列表初始化。
如果需要更灵活的初始化逻辑,也可以提供静态工厂函数:
class Bar { int a; std::string s; float f; public: static Bar create(int a_, std::string s_, float f_) { Bar instance; instance.a = a_; instance.s = std::move(s_); instance.f = f_; return instance; } };
使用方式为auto obj2 = Bar::create(0, "", 0.0f);,虽不属于直接列表初始化,但能实现相同的初始化效果。
2. 能否让编译器自动生成具备类似功能的构造函数?
不能。编译器自动生成的构造函数仅包括默认构造函数、拷贝构造函数、移动构造函数,不会自动生成适配列表初始化的带参构造函数。
核心原因是:支持列表初始化的**聚合类(Aggregate Class)**要求所有非静态数据成员必须是公有的,而Bar的成员为私有,不符合聚合类的定义,因此编译器不会为其生成支持列表初始化的构造逻辑。若要实现该功能,必须手动显式定义构造函数。
内容的提问来源于stack exchange,提问作者Isuxiz Slidder
相关产品推荐
相关产品推荐

