C ++ неопределенный конструктор абстрактных классов - PullRequest
0 голосов
/ 24 февраля 2012

В последнее время у меня возникли некоторые проблемы в 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;
};

Ответы [ 5 ]

2 голосов
/ 24 февраля 2012

Попробуйте

GameState() { }

вместо

GameState();

или определите его где-нибудь еще.

Хотя я не уверен, имеет ли это какое-либо отношение квиртуальные методы.Я думаю, что есть ошибка в другом месте.Возможно, неинициализированный указатель?

1 голос
/ 24 февраля 2012

Вот полная программа, которая реализует базовые и производные классы, которые вы ищете.Вы получаете сообщение об ошибке компоновщика, потому что вы никогда не внедрили 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;
}
1 голос
/ 24 февраля 2012

Вам нужно предоставить реализацию для конструктора, если вы хотите явно вызвать его:

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;
};
0 голосов
/ 24 февраля 2012

Эта ошибка 'Undefined reference to GameState::GameState()' говорит о том, что конструктор GameState не определен. Это не имеет ничего общего с виртуальным методом.

Делайте, что @Luchian и @Micheal сказали:

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

Если бы это была ошибка виртуального метода, вы бы получили что-то вроде "the 'MainGameState' must implement inherited pure virtual method 'method name'"

РЕДАКТИРОВАНИЕ: Обратите внимание, что конструктор суперкласса вызывается неявно при создании экземпляра подкласса.

0 голосов
/ 24 февраля 2012
  1. Компилятор в любом случае вызовет для вас конструктор базового класса без параметров (конструктор по умолчанию), поэтому в этом нет необходимости.Тем не менее, вы даже предоставляете определение для GameState::GameState()?Вероятно, нет, поэтому вы должны просто избавиться от этого или предоставить реализацию (т. Е. GameState() { }).

  2. Нам нужно посмотреть, как вы вызываете функцию.Это выглядит хорошо для меня, ваша ошибка где-то еще.Возможно, вы объявляете указатель на объект, не инициализируете его, а затем вызываете update()?

Если бы мне пришлось угадывать (и, очевидно, я делаю ...), я бы поставилчто у вас есть что-то вроде этого:

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

Конечно, я могу ошибаться, но, как я уже сказал, я вынужден угадывать, пока вы не обновите свой вопрос реальным кодом.

...