如何用抽象基类直接初始化派生类?
问题原因与解决方法
你遇到的编译失败问题和虚函数本身的直接初始化规则无关,核心在于聚合类的判定条件:
- 当
Base没有虚函数时,Derived在C++17及以后属于聚合类(满足聚合类的所有要求:无用户声明构造函数、无私有/保护非静态成员、基类也是聚合类等)。此时make_unique<Derived>(Base{}, 3)本质是对聚合类进行聚合初始化:第一个参数初始化基类部分,第二个参数初始化成员i,因此可以正常编译。 - 当
Base包含虚函数时,Derived不再符合聚合类的判定条件(基类存在虚函数会打破聚合类的要求)。此时编译器不会为Derived自动生成接受Base对象和int的构造函数,make_unique找不到匹配的构造函数,因此编译失败。
解决方法
方法1:为Derived定义显式构造函数
这是最直接且清晰的方案,自定义构造函数来接收基类对象和成员参数:
#include <memory> #include <utility> // 用于std::move struct Base { virtual void method() {}; // 注意:虚方法需提供定义,否则会出现链接错误 }; struct Derived : public Base { int i; // 定义构造函数,初始化基类和成员 Derived(Base b, int val) : Base(std::move(b)), i(val) {} }; int main() { Base base{}; auto ptr = std::make_unique<Derived>(Base{}, 3); // 现在可正常编译 }
方法2:直接初始化Derived对象后传递给make_unique
如果不想定义构造函数,可以先构造Derived对象再传入make_unique:
#include <memory> struct Base { virtual void method() {}; }; struct Derived : public Base { int i; }; int main() { Base base{}; Derived d{}; static_cast<Base&>(d) = Base{}; // 赋值基类部分 d.i = 3; auto ptr = std::make_unique<Derived>(std::move(d)); }
内容的提问来源于stack exchange,提问作者Spongman
相关产品推荐
相关产品推荐

