【问题标题】:Why i getting unresolved externals error when declaring virtual functions in parent class?为什么在父类中声明虚函数时出现未解决的外部错误?
【发布时间】:2012-07-12 05:20:24
【问题描述】:

我有这个父类:

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

还有编译错误:(

Error 9 error LNK1120: 3 unresolved externals
Error 8 error LNK2001: unresolved external symbol "public: virtual void __thiscall UserInterface::GAMEPLAY_SCREEN_HideTargetBox(void)" (GAMEPLAY_SCREEN_HideTargetBox@UserInterface@@UAEXXZ)
Error 7 error LNK2001: unresolved external symbol "public: virtual void __thiscall UserInterface::GAMEPLAY_SCREEN_ShowTargetBox(void)" (GAMEPLAY_SCREEN_ShowTargetBox@UserInterface@@UAEXXZ)
Error 6 error LNK2001: unresolved external symbol "public: virtual void __thiscall UserInterface::update(void)" (?update@UserInterface@@UAEXXZ)

有人知道如何摆脱这些错误吗?

【问题讨论】:

    标签: c++ class function virtual parent


    【解决方案1】:

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

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

    在你的 cpp 文件中使用UserInterface 的实现添加这些:

    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;
    

    【讨论】:

    • 谢谢,void UserInterface::update() { } 帮助了我!
    • 您应该补充一点,后者不适用于纯虚拟析构函数,它们应该始终有一个主体。
    【解决方案2】:

    因为您需要为 UserInterface::GAMEPLAY_SCREEN_HideTargetBox 定义一个主体(如果这对您和您的应用程序的逻辑来说可以的话,它可能是一个空实现)。

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

    virtual void GAMEPLAY_SCREEN_HideTargetBox() = 0;
    

    这将使您的基类 UserInterface 抽象(您将无法创建类型为 UserInterface 的对象)和所有派生类(您希望是非抽象的)必须为此函数定义主体。

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

    【讨论】:

      【解决方案3】:

      很快,它是“基”类和“派生”类(或“子类”),而不是父类和子类。

      我从事 C++ 工作已经十年了,但我认为问题在于您的 LoginScreenUserInterface 类没有实现虚拟方法。如果一个虚方法没有被覆盖,那么基类实现就会被调用。由于您没有方法基类实现。您收到链接错误。如果你想拥有一个没有默认实现的虚拟基类,你应该通过在末尾添加一个 = 1 来将其声明为纯虚拟:

      虚空更新() = 0;

      这将强制任何派生类提供实现。如果您不想强制派生类提供实现,请在基类中提供类似 { } 的内容。

      【讨论】:

      • “我相信问题是因为你的 LoginScreenUserInterface 类没有实现虚拟方法”如果我将这些函数声明为纯虚拟方法,这应该是正确的。现在我明白我只需要在基类中为它们提供实现
      • 好的,但答案在这部分包含错误信息:“我相信问题是因为您的 LoginScreenUserInterface 类没有实现虚拟方法。如果没有覆盖虚拟方法,那么基类实现是叫了。”只有当我确实将这些函数声明为纯虚拟函数时,这一切都是真实的
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2014-01-23
        • 1970-01-01
        • 2023-03-28
        • 2019-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        相关资源
        最近更新 更多