C++ template结合shared_ptr编译时找不到A默认构造函数解决方法
报错根因
C++的类构造有个硬规则:所有非静态成员变量必须在构造函数执行完毕前完成初始化。如果你没在构造函数的初始化列表里明确写某个成员怎么初始化,编译器会自动调用这个成员类型的无参构造来初始化它,这个逻辑和你外部传了什么参数进来没有任何关系。
对应到你的代码,问题出在两个地方:
- 你给
A类写了一个接收const std::string&参数的构造函数,这种情况下编译器不会再自动给A生成无参的默认构造函数。 - 类
B的构造函数初始化列表里只初始化了field1,剩下两个成员A field2、CLIENT field3(你实例化的是B<A>,所以field3的类型也是A)都没写初始化逻辑,编译器就会尝试调用A的无参构造来初始化这俩成员,找不到自然就报错了。
你在main函数里提前创建的a只是传给B构造函数的实参,只用来初始化你显式指定的field1,和B自己持有的field2、field3完全没关系——这俩是每个B实例独立占有的成员,必须单独初始化,不可能直接复用外部的a对象。另外这个报错和std::make_shared没关系,它只是负责把你传入的a转发给B的构造函数,问题根源在B自己的构造逻辑上。
修复方案
根据你的实际业务需求二选一就行:
- 方案1:给
A补充无参默认构造
如果你允许A的对象不传入参数直接创建,直接在A的public权限区域加一行声明即可:
注意用这个方案的话,class A { private: std::string field1; std::string field2; public : A() = default; // 显式指定编译器生成无参构造 A(std::string const& s1):field1(s1){}; virtual ~A(){}; };B里的field2和field3会走无参构造,后续你要记得给它们赋值再使用,避免出现值不符合预期、甚至未定义行为的问题——毕竟你原来的muFunc是直接返回field3的。 - 方案2:在
B的构造函数里显式初始化所有成员(推荐)
不需要改动A的代码,直接在B的初始化列表里把所有成员的初始化逻辑写全即可,示例(初始值可以按你实际业务逻辑调整):
这种写法没有额外的性能开销,也能从根源上避免成员漏初始化的问题,是更规范的写法。B(A const& a1): field1(a1), field2(a1), field3(std::string("init_val")) {};
内容的提问来源于stack exchange,提问作者Ioan Le Gué
相关产品推荐
相关产品推荐

