2017-07-24 307 views
0

有没有办法从其中一个继承类创建unique_ptr如何从继承父类创建unique_ptr

我需要能够“注册”MouseListeners与经理,但我不知道如何创建继承MouseListenerunique_ptr

错误在于它无法找到从Window *MouseListener的转换。我试过static_cast但是会产生其他错误。我也尝试传递raw pointeraddMouseListener,它确实有效,但在关闭程序时出错,因为我认为它没有创建导致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()这将导致其如上所述所有权的变更导致事件不起火。

+1

1.您是否阅读过错误信息? 2.创建一个[mcve]。 – user2079303

+0

我指定了这个实现的错误。 “它无法找到从'Window *'到'MouseListener'的转换,我会发布错误日志,以便在人们错过的情况下提供额外的清晰度 – Matthew

+1

MouseListener的构造函数是什么? – 0x499602D2

回答

0
std::make_unique<MouseListener>(this) 

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

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

std::unique_ptr<Window>(this) 

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


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

+0

所以如果我明白你正确地从'MouseListener'继承'Window'是好的,但是使用类似全局的'MouseManager'? – Matthew

+0

从'MouseListener'继承'Window'违反了单一责任原则。使用组合物可能是一个不太臭的设计。 – user2079303

+0

看完作文之后,看起来好像你说在Window类中有一个变量'MouseListener'是个好主意? – Matthew

1

make unique使该类型的对象返回指向它的指针。

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

您的addMouseListener(std::unique_ptr<MouseListener>)函数取得了监听者的所有权。传递一个先前的对象在这里通常不是一个好主意。

也许Window不应MouseListener继承,而是创建一个MouseListener,反过来有一个指针Window并以某种方式做生命周期管理,以确保各地Window活着住宿,或者我们Window模具时断开连接。

MouseListener应该中继消息发送到窗口中,不窗口。