请求从 'std::unique_ptr<derived, std::default_delete<derived> >' 转换为非标量类型 'std::unique_ptr<base>'|

conversion from 'std::unique_ptr<derived, std::default_delete<derived> >' to non-scalar type 'std::unique_ptr<base>' requested|

我目前正在使用网络上的多个资源为游戏制作状态机。 但是,当我尝试创建一个 State 并将其放入 StateMachine 时,我的问题就来了。 错误在 StateGameMenu.cpp,在 sendConnexion.

StateGameMenu.h

#ifndef STATEGAMEMENU_H
#define STATEGAMEMENU_H
#include <TGUI/TGUI.hpp>

#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>

#include <memory>
#include <thread>

#include "Log.h"
#include "Client.h"
#include "Personnage.h"
#include "State.hpp"

class StateMachine;

class StateGameMenu : public State
{
    public:
        StateGameMenu(Context& context);

        virtual ~StateGameMenu();

    protected:
        void sendConnexion(tgui::EditBox::Ptr username, tgui::EditBox::Ptr password);
        void loadGUI();

    private:
};

#endif // STATEGAMEMENU_H

StateGameMenu.cpp,我的错误所在。

#include "StateGameMenu.h"
#include "StateGamePlay.h"

#include "StateMachine.h"

StateGameMenu::StateGameMenu(Context& context) : State(context)
{
    //ctor
}
void StateGameMenu::sendConnexion(tgui::EditBox::Ptr username, tgui::EditBox::Ptr password)
{
    m_context.Client->connexion(username->getText().toAnsiString(), password->getText().toAnsiString());
    if(m_context.Client->estConnecte())
    {
        ///The line below is the line triggering an error. 
        std::unique_ptr<State> temp = StateMachine::build<StateGamePlay>(m_context); ///The problem is here.
        m_context.Machine->askPush(std::move(temp), true);
    }
}
void StateGameMenu::loadGUI()
{
    /* Some GUI Stuff ... */

    button->connect("pressed", StateGameMenu::sendConnexion, this, editBoxUsername, editBoxPassword);
}
StateGameMenu::~StateGameMenu(){}

错误是:

conversion from 'std::unique_ptr<StateGamePlay, std::default_delete<StateGamePlay> >' to non-scalar type 'std::unique_ptr<State>' requested|

我真的很难理解为什么函数 "build" 的输出不只是 "std::unique_ptr".

StateGamePlay.h

#ifndef STATEGAMEPLAY_H
#define STATEGAMEPLAY_H

#include "State.hpp"

class StateMachine;

class StateGamePlay : State
{
    public:
        StateGamePlay(Context& context);

        virtual ~StateGamePlay();

    protected:

    private:
};

#endif // STATEGAMEPLAY_H

StateGamePlay.cpp

#include "StateGamePlay.h"

#include "StateMachine.h"

StateGamePlay::StateGamePlay(Context& context) : State(context)
{
    //ctor
}

更多信息: StateMachine.h

#ifndef STATEMACHINE_H
#define STATEMACHINE_H

#include <SFML/Graphics.hpp>

#include <stack>
#include <memory>

#include "Log.h"
#include "Context.h"

class State;

class StateMachine
{
    public:
        typedef std::unique_ptr<State> StatePtr;


        StateMachine();
        void askPush(StatePtr state, bool isReplacing = true);
        void askPop();

        template <typename T>
        static std::unique_ptr<T> build( Context& context );

        void processStateChanging();

        virtual ~StateMachine();

    protected:
        void push();
        void pop();
        void resume();
        void pause();

        void modifyState();

        std::stack<StatePtr> m_States;
        bool m_isReplacing;
        bool m_isChanging;
        bool m_isDeleting;
        StatePtr m_FutureChangingState;

    private:
};

#include "State.hpp"

template <typename T>
std::unique_ptr<T> StateMachine::build( Context& context )
{
    //return  std::unique_ptr<T>( new T(context) );
    return std::make_unique<T>( context );
}

#endif // STATEMACHINE_H

问题似乎直接与模板函数有关,但我看不出那部分有什么问题,调用似乎也写对了。

State.hpp

#ifndef STATE_H
#define STATE_H

#include <SFML/Graphics.hpp>
#include <TGUI/TGUI.hpp>

#include <memory>

#include "Client.h"
#include "Context.h"

class StateMachine;

class State
{
    public:

        State(Context& context);
        State ( const State& ) = delete;
        State& operator= ( const State& ) = delete;

        void pause() {inPause = true;};
        void resume() {inPause = false;};

        virtual ~State();

    protected:
        bool inPause;
        Context m_context;

    private:
};

#endif // STATE_H

Context.h

#ifndef CONTEXT_H_INCLUDED
#define CONTEXT_H_INCLUDED

#include <SFML/Graphics.hpp>
#include <TGUI/TGUI.hpp>

#include <memory>

#include "Client.h"

class StateMachine;

struct Context
{
    typedef std::shared_ptr<sf::RenderWindow> WindowPtr;
    typedef std::shared_ptr<StateMachine> MachinePtr;
    typedef std::shared_ptr<tgui::Gui> GuiPtr;
    typedef std::shared_ptr<Client> ClientPtr;

    Context(WindowPtr window, MachinePtr machine, GuiPtr gui, ClientPtr client);
    WindowPtr Window;
    MachinePtr Machine;
    GuiPtr Gui;
    ClientPtr Client;
};
Context::Context(WindowPtr window, MachinePtr machine, GuiPtr gui, ClientPtr client) :
Window(window), Machine(machine), Gui(gui), Client(client)
{ }

#endif // CONTEXT_H_INCLUDED

最后,我编写该部分的主要资源之一是 eXpl0it3r 的 https://github.com/eXpl0it3r/SmallGameEngine/tree/master/(这是对其他代码的更改)。 在这段代码中,将 State 赋予 StateMachine 的方式与我的非常相似,但它在我的情况下不起作用,我不知道为什么。 是的,我可以在这个上克隆我的代码,但我更喜欢自己做。

我希望我的 post 不会太长和模糊,因为我自己真的很困惑。 (而且我没有找到任何东西来回答我的问题。) 感谢您阅读整篇 post 以及您抽出宝贵的时间! (抱歉我的英语不好)。

无法创建 StateGamePlay 的实例,因为 State 构造函数是私有的。

class StateGamePlay : State // default private inheritance

应该是

class StateGamePlay : public State