如何从继承的父类创建unique_ptr

how to create unique_ptr from inherited parent class

本文关键字:创建 unique ptr 父类 继承      更新时间:2023-10-16

有没有办法从继承的类之一创建unique_ptr

我需要能够向经理"注册"MouseListeners,但我无法弄清楚如何创建继承MouseListenerunique_ptr

错误是它找不到从Window *MouseListener的转换。我尝试了一个static_cast,但这会产生其他错误。我还尝试将raw pointer传递给确实有效的addMouseListener,但是当您关闭程序时出错,因为我认为它没有创建导致delete失败的适当内存。

此外,使用std::move()会转移所有权,从而导致侦听器不触发事件。

// Window.h
class Window : public MouseManager, public MouseListener {
public:
Window::Window(std::string title, int32_t width, int32_t height) {
...
this->addMouseListener(std::make_unique<MouseListener>(this)); // ERROR
}
};
// MouseManager.h
void MouseManager::addMouseListener(std::unique_ptr<MouseListener> listener) {
m_listeners.emplace_back(listener);
}
// MouseListener.h
MouseListener() = default;
virtual ~MouseListener() = default;
MouseListener(const MouseListener& listener) = default;
MouseListener(MouseListener&& listener) noexcept ;
MouseListener& operator=(const MouseListener& listener) = delete;
MouseListener& operator=(MouseListener&& listener) = delete;

错误输出

In file included from /Users/Programmer/CLionProjects/StormEngine/Engine/Window/Window.cpp:5:
In file included from /Users/Programmer/CLionProjects/StormEngine/Engine/Window/Window.h:8:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3141:32: error: no matching constructor for initialization of 'MouseListener'
return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...));
^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/Programmer/CLionProjects/StormEngine/Engine/Window/Window.cpp:17:33: note: in instantiation of function template specialization 'std::__1::make_unique<MouseListener, Window *>' requested here
this->addMouseListener(std::make_unique<MouseListener>(this));
^
/Users/Programmer/CLionProjects/StormEngine/Engine/Window/../Events/Listeners/MouseListener.h:19:5: note: candidate constructor not viable: no known conversion from 'Window *' to 'const MouseListener' for 1st argument; dereference the argument with *
MouseListener(const MouseListener& listener) = default;
^
/Users/Programmer/CLionProjects/StormEngine/Engine/Window/../Events/Listeners/MouseListener.h:20:5: note: candidate constructor not viable: no known conversion from 'Window *' to 'MouseListener' for 1st argument; dereference the argument with *
MouseListener(MouseListener&& listener) noexcept ;
^
/Users/Programmer/CLionProjects/StormEngine/Engine/Window/../Events/Listeners/MouseListener.h:16:5: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
MouseListener() = default;
^

更新:

取消引用this增加了一个新问题,listener您必须std::move()添加变量,这会导致所有权更改,如上所述,这会导致事件不触发。

make unique创建该类型的对象并返回指向它的指针。

它不会将指向对象的预先存在的指针包装到唯一的 ptr 中。

您的addMouseListener(std::unique_ptr<MouseListener>)函数取得侦听器的所有权。 在这里,传递预退出对象通常不是一个好主意。

可能Window不应该从MouseListener继承,而是创建一个MouseListener,而又有一个指向Window的指针,并以某种方式进行生命周期管理,以确保活着的Window留在身边,或者在Window死亡时我们断开连接。

MouseListener应将消息中继到窗口,而不是窗口。

std::make_unique<MouseListener>(this)

这将分配一个新的MouseListener实例,this作为构造函数的参数。正如错误消息所解释的那样,没有构造函数MouseListener:MouseListener(Window*)或任何其他构造函数具有可以将Window*隐式转换为的参数。

您可能不打算创建新的MouseListener实例,而是想要一个指向this的唯一指针。您可以使用构造函数explicit unique_ptr(pointer p)创建要thisunique_ptr

std::unique_ptr<Window>(this)

此指针可以传递给MouseManager::addMouseListener。请注意,虽然从 deriver 唯一指针的转换是隐式的,但基唯一指针不能直接从裸派生指针构造,因为构造函数是显式的。


请注意,创建指向this的唯一指针可能是一个可疑的想法。它将Window对象的创建限制为使用new,并且显然(从分配的代码的角度来看(泄漏了指针。没有其他代码可以拥有任何窗口(除非从最初存储它的容器中移动(,并且您永远不能拥有自动实例。