为什么这段代码不能编译?
#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
最佳答案
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
。
|
std::unique_ptr<Derived> base_ptr =...
在问这个问题之前,您是否尝试过将其更改为?–
–
|