为什么这段代码不能编译?

#include <memory>
    
struct Base {
};
    
struct Derived: Base {
    int n;
};
    
int main() {
    std::unique_ptr<Base> base_ptr = std::make_unique<Derived>(5);
}

我查看了unique_ptr源代码,它似乎允许移动unique_ptr派生类的

我需要这个,这样我就可以收集不同类型的消息,以便进一步处理它们

编译器输出:

/usr/include/c++/13/bits/unique_ptr.h:1070:30: error: could not convert ‘std::forward<int>((* & __args#0))’ from ‘int’ to ‘arb::exchange_connector::Base’
  1070 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

2

  • 1
    std::unique_ptr<Derived> base_ptr =...在问这个问题之前,您是否尝试过将其更改为?


    – 

  • 您无法分配unique_ptr。最终 move()


    – 



最佳答案
2

它与类层次结构无关,但与它Derived是一个聚合并且您不能像那样make_unique用于聚合初始化的事实有关。

您的代码也将同样无法通过编译std::unique_ptr<Derived>

std::unique_ptr<Derived> ptr = std::make_unique<Derived>(5);

一个解决方案是向添加一个构造函数Derived

代码中的另一个问题是,为了Derived通过Base指针正确地析构,您必须向添加虚拟析构函数Base

如下所示:

#include <memory>

struct Base {
    // Add a virtual destructor:
    virtual ~Base() {}
};

struct Derived : Base {
    // Add this constructor:
    Derived(int n_) : n(n_) {}

    int n;
};

int main() {
    std::unique_ptr<Base> base_ptr = std::make_unique<Derived>(5);
}

5

  • 啊,当然你说得对。


    – 

  • 4
    并添加virtual析构函数Base以避免UB。


    – 

  • @Jarod42 很好的观点 — 已添加。


    – 

  • 伙计们,非常感谢,我觉得自己在 C++ 方面还很菜。我以为结构会有默认构造函数。upd – 它实际上有,那么为什么它不能在 make_unique 中调用?


    – 


  • @baltazar 我刚刚在评论中看到了你关于结构默认构造函数的问题。我不确定具体原因(对于语言律师来说,这将是一个不同的问题,而我不是),但由于它Derived 是一个聚合,因此它不被视为可以使用成员参数调用的构造函数(这是必需的std::make_unique)。在这方面,聚合初始化与“正常”构造不同。您可以查看有关聚合的更多信息。


    – 


另一个选择是提供一个初始化程序Base

std::make_unique<Derived>(Base{}, 5)

并且,正如另一个答案中提到的,不要忘记向中添加虚拟析构函数Base