C++ 为什么我在父类中声明虚拟函数时遇到未解决的外部错误?

C++ 为什么我在父类中声明虚拟函数时遇到未解决的外部错误?,c++,class,function,virtual,parent,C++,Class,Function,Virtual,Parent,我有一个父类: enum UI_STATE { UI_STATE_SPLASH_SCREEN, UI_STATE_LOGIN_SCREEN, UI_STATE_CHARACTER_CREATION_SCREEN, UI_STATE_CHARACTER_CHOOSE_SCREEN, UI_STATE_LOADING_SCREEN, UI_STATE_GAMEPLAY, UI_STATE_EXIT_REQUESTED, UI_STATE

我有一个父类:

enum UI_STATE
{
    UI_STATE_SPLASH_SCREEN,
    UI_STATE_LOGIN_SCREEN,
    UI_STATE_CHARACTER_CREATION_SCREEN,
    UI_STATE_CHARACTER_CHOOSE_SCREEN,
    UI_STATE_LOADING_SCREEN,
    UI_STATE_GAMEPLAY,
    UI_STATE_EXIT_REQUESTED,
    UI_STATE_UNKNOWN
};

[event_source(native)]
class UserInterface
{
protected:
    MyGUI::Gui *mGUI;

public:
    static UserInterface *Instance;
    UI_STATE UI_CURRENT_STATE;

public:
    UserInterface()
    {
        MyGUI::OgrePlatform* mPlatform = new MyGUI::OgrePlatform();
        mPlatform->initialise(BaseObjects::mWindow, BaseObjects::mSceneMgr);
        mGUI = new MyGUI::Gui();
        mGUI->initialise();

        UI_CURRENT_STATE = UI_STATE_UNKNOWN;
    }

    ~UserInterface()
    {
        mGUI->destroyAllChildWidget();
        mGUI->shutdown();

        delete mGUI;
        mGUI = NULL;

        delete Instance;
        Instance = NULL;
    }

    virtual void update();
    virtual void GAMEPLAY_SCREEN_ShowTargetBox();
    virtual void GAMEPLAY_SCREEN_HideTargetBox();

...//some other methods
}

UserInterface *UserInterface::Instance = NULL;
还有两个子类,其中一个是重写这3个虚拟函数,第二个是不使用这3个函数

儿童1:

#ifndef GameplayScreenInterface_h
#define GameplayScreenInterface_h

#include "UserInterface.h"
#include "ControllableCharacterAdv.h"

class GameplayScreenUserInterface : public UserInterface
{
private:
...

public:
    GameplayScreenUserInterface()
    {
...
    }

    void GAMEPLAY_SCREEN_ShowTargetBox()
    {
        ...
    }

    void GAMEPLAY_SCREEN_HideTargetBox()
    {
        ...
    }

    void update()
    {
        UpdateTargetBox();
        UpdateCharacterBox();
    }

    void UpdateCharacterBox()
    {
...
    }

    void UpdateTargetBox()
    {
        if (...)
        {
            if (...)
            {
            ...
            }
            else if (...)
            {
...
            }
            else
            {
            ...
            }
        }
        else
            GAMEPLAY_SCREEN_HideTargetBox();
    }
};

#endif GameplayScreenInterface_h
儿童2:

#ifndef LoginScreenInterface_h
#define LoginScreenInterface_h

#include "UserInterface.h"
#include "NetworkManager.h"

class LoginScreenUserInterface : public UserInterface
{
public:
    LoginScreenUserInterface()
    {
...
    }
};

#endif LoginScreenInterface_h
和编译错误:(


有人知道如何消除这些错误吗?

因为您需要为
UserInterface::GAMEPLAY\u SCREEN\u HideTargetBox定义一个主体(如果这对您和应用程序逻辑都合适的话,它可能是一个空的实现)

如果不想在基类中定义此函数,请将其设置为纯虚拟:

virtual void GAMEPLAY_SCREEN_HideTargetBox() = 0;
这将使基类
UserInterface
抽象(您将无法创建类型为
UserInterface
的对象),并且所有派生类(您希望非抽象的)必须为此函数定义主体


注意:这些是链接器错误,而不是编译器错误。

这些不是编译错误,这些是链接错误。您的源代码编译得很好,但您没有在基类中提供三个虚拟函数的实现

当您在类声明中提到成员函数时,您所做的只是声明函数:您告诉编译器函数的名称、参数类型和返回类型;这使编译器感到高兴。您仍然需要提供一些实现,或将函数标记为抽象的,以满足链接器

在实现了
UserInterface
的cpp文件中,添加以下内容:

void UserInterface::update() {
    // default implementation
}
void UserInterface::GAMEPLAY_SCREEN_ShowTargetBox() {
    // default implementation
}
void UserInterface::GAMEPLAY_SCREEN_HideTargetBox() {
    // default implementation
}
或者,如果某些或所有虚拟函数没有默认实现,请在标题中添加
=0

virtual void update() = 0;
virtual void GAMEPLAY_SCREEN_ShowTargetBox() = 0;
virtual void GAMEPLAY_SCREEN_HideTargetBox() = 0;
很快,它是“基类”和“派生类”(或“子类”),而不是父类和子类


我在C++上工作了十年,但是我相信问题是因为Login StudioServer接口类没有实现虚拟方法。如果没有重写虚拟方法,那么调用基类实现。因为没有方法基类实现。没有默认实现的虚拟基类,应通过在末尾添加an=1将其声明为纯虚拟:

虚拟void update()=0


这将强制任何派生类提供实现在基类中。

编译器无法通过查看源代码来证明没有人会单独实例化父类。因此,它会为父类创建虚拟方法表,为了初始化该表,链接器会查找父类函数的地址


为了避免这种情况,您需要通过在定义中附加=0来声明父函数为纯虚拟。这样,编译器将禁止自己实例化父类,并将NULL放入VMT中,而链接器无需查找。

谢谢,使用void UserInterface::update(){}帮助了我!你应该补充一点,后者不适用于纯虚拟析构函数,它们应该始终有一个主体。“我相信问题是因为你的LoginsScreenUserInterface类没有实现虚拟方法”如果我将这些函数声明为纯虚拟函数,这应该是正确的。现在我知道我只需要在基类OK中为它们提供实现,但答案在这一部分中包含错误的信息:“我认为问题是因为LoginsScreenUserInterface类未实现虚拟方法。如果未重写虚拟方法,则会调用基类实现。”只有在我将这些函数声明为纯虚拟函数时,这才是实际的
virtual void update() = 0;
virtual void GAMEPLAY_SCREEN_ShowTargetBox() = 0;
virtual void GAMEPLAY_SCREEN_HideTargetBox() = 0;