【问题标题】:C++ Undefined abstract class constructorC++ 未定义的抽象类构造函数
【发布时间】:2012-02-23 22:02:31
【问题描述】:

我最近在使用虚拟方法/继承的 C++ 中遇到了一些麻烦

起初,如果我尝试扩展一个超类,我会得到这个错误:

'未定义对 GameState::GameState() 的引用'

但是如果我一起删除构造函数,我不会得到上述错误,但我最终会在调用虚拟方法时出现分段错误。

这是我的代码:

#ifndef GAMESTATE_H
#define GAMESTATE_H

#include <stdlib.h>

#include "Resources.h"
#include "Renderer.h"

class GameState {
public:
    GameState();
    virtual void init(Resources *res) = 0;
    virtual void exit() = 0;
    virtual void update() = 0;
    virtual void render(Renderer *renderer) = 0;
};

#endif // GAMESTATE_H

这是子类:

#include "GameState.h"

class MainGameState : public GameState {
public:
    MainGameState() : GameState() {

    }

    virtual void init(Resources *res) {

    }

    virtual void update() {
        printf("test\n");
    }

    virtual void render(Renderer *renderer) {

    }

    virtual void exit() {

    }
private:
    SDL_Surface *image;
};

【问题讨论】:

  • 你在哪里定义GameState::GameState
  • 你是如何使用这些类的
  • 也许发布一个示例调用。您也可以尝试询问 valgrind 是什么导致了分段错误
  • 你的第一个错误是因为抽象类GameState没有给它的构造函数定义,但是MainGameState构造函数调用了它。只需将 GameState(); 更改为 GameState() { } 即可解决此问题。如果您在段错误之前告诉我们您正在调用哪个虚拟方法,我们可以在第二个方面提供更多帮助。

标签: c++ inheritance segmentation-fault abstract-class


【解决方案1】:

试试

GameState() { }

而不是

GameState();

或在其他地方定义它。

不过,我不确定它是否与虚拟方法有关。我认为其他地方存在错误。也许,未初始化的指针?

【讨论】:

    【解决方案2】:

    如果你想显式调用它,你需要为构造函数提供一个实现:

    class GameState {
    public:
        GameState() {} // implementation
        virtual void init(Resources *res) = 0;
        virtual void exit() = 0;
        virtual void update() = 0;
        virtual void render(Renderer *renderer) = 0;
    };
    

    【讨论】:

    • 我认为您不应该在此处放置分号。
    【解决方案3】:

    这是一个完整的程序,它实现了您正在寻找的基类和派生类。您收到链接器错误消息是因为您从未实现过GameState::GameState。目前尚不清楚您为什么会遇到分段错误。

    还请记住,如果您想以多态方式删除对象,请声明并定义一个虚拟基类析构函数。

    #include <iostream>
    #define X() (std::cout << __FUNCTION__ << "\n")
    class GameState {
    public:
      GameState() { X(); }
      virtual ~GameState() { X(); }
      virtual void F() = 0;
    };
    
    class MainGameState : public GameState {
    public:
      MainGameState() : GameState() { X(); }
      void F() { X(); }
      ~MainGameState() { X(); }
    };
    
    int main () {
      GameState* pGS = new MainGameState;
      X();
      pGS->F();
      delete pGS;
    }
    

    【讨论】:

      【解决方案4】:

      此错误'Undefined reference to GameState::GameState()' 告诉您未定义 GameState 构造函数。与虚方法无关。

      按照@Luchian 和@Micheal 所说的去做:

      class GameState {
      public:
          GameState() {} // implementation
      

      如果是虚方法错误,你会得到类似"the 'MainGameState' must implement inherited pure virtual method 'method name'"

      编辑:请注意,当您实例化子类时,会隐式调用超类构造函数。

      【讨论】:

        【解决方案5】:
        1. 编译器无论如何都会为你调用一个无参数的基类构造函数(默认构造函数),所以没有必要。但是,您是否甚至提供了GameState::GameState() 的定义?可能不是,所以你应该摆脱它或提供一个实现(即GameState() { })。

        2. 我们需要看看你是如何调用函数的。这对我来说看起来不错,你的错误在其他地方。您是否可能声明了一个指向对象的指针,而不是对其进行初始化,然后调用update()

        如果我必须猜测(显然我会......)我敢打赌你有这样的事情:

        MainGameState *state;
        state->update();  // oops!  Not initialize!
        

        当然我可能是错的,但就像我说的,我不得不猜测,直到你用真实代码更新你的问题。

        【讨论】:

        • @LuchianGrigore:哈哈,是的,我知道,那是精神上的昙花一现。我经常在 C# 和 C++ 之间来回切换,以至于我有时会混淆两者之间的语法。在您发表评论之前,我已将其编辑掉。谢谢。
        • 此外,该术语是“默认构造函数”。你可能已经知道了,我猜你使用了无参数,所以操作更容易理解。
        • @LuchianGrigore:是的,我知道,默认构造函数是无参数的。
        • :) 我想通了。在写完整个评论之前,我只是按了 Enter 键 :)
        • @LuchianGrigore:是的,不过你是对的;与相对的初学者交谈时使用共同语言并没有什么坏处,以免他们将来感到困惑。我只是希望我能看到他是如何调用出错的函数......
        猜你喜欢
        • 2023-03-04
        • 1970-01-01
        • 2011-08-01
        • 1970-01-01
        • 2018-06-10
        • 2015-11-17
        • 1970-01-01
        • 2013-11-17
        • 1970-01-01
        相关资源
        最近更新 更多