You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用抽象基类直接初始化派生类?

问题原因与解决方法

你遇到的编译失败问题和虚函数本身的直接初始化规则无关,核心在于聚合类的判定条件:

  • 当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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:45:06