(Я довольно новичок в C ++, так что, надеюсь, это просто ошибка новичка)
У меня проблемы в моем коде, где у меня есть класс «Player», которому нужен ряд атрибутов, которые я пытаюсь дать ему, используя абстрактные классы как таковые:
//player.h
class Player : public IUpdate, public IPositionable, public IMoveable, public IDrawable
{
public:
Player(void);
SDL_Rect get_position();
void move(Uint32 dTime);
void update(Uint32 dTime);
void show(SDL_Surface* destination);
~Player(void);
private:
SDL_Surface texture;
int x, y;
};
И я переопределяю чисто виртуальные функции как таковые:
//Player.cpp
Player::Player(void)
{
}
SDL_Rect Player::get_position()
{
SDL_Rect rect;
rect.h = 0;
return rect;
}
void Player::move(Uint32 dTime)
{
}
void Player::update(Uint32 dTime)
{
move(dTime);
}
void Player::show(SDL_Surface* destination)
{
apply_surface(x, y, &texture, destination, NULL);
}
Player::~Player(void)
{
}
Однако я продолжаю получать ошибку компиляции: C2259: 'Player' : cannot instantiate abstract class
Насколько я вижу, чисто виртуальные функции должны быть переопределены, что, как сказали мне мои поиски в Google, сделало бы Player неабстрактным, хотя Player по-прежнему выглядит абстрактным.
РЕДАКТИРОВАТЬ:
Чистые виртуальные функции:
class IPositionable
{
public:
virtual SDL_Rect get_position() = 0;
private:
int posX, posY;
};
class IUpdate
{
public:
virtual void update (Uint32 dTime) = 0;
};
class IMoveable
{
public:
int velX, velY;
virtual void move(Uint32 dTime) = 0;
};
class IDrawable
{
public:
virtual void show() = 0;
private:
SDL_Surface texture;
};
class IHitbox
{
virtual void check_collsion() = 0;
};
class IAnimated
{
virtual void next_frame() = 0;
int state, frame;
int rows, columns;
};
Ваша проблема здесь:
class IDrawable
{
public:
virtual void show() = 0;
};
void Player::show(SDL_Surface* destination)
{
apply_surface(x, y, &texture, destination, NULL);
}
Обратите внимание, что Player::show(SDL_Surface* destination)
не переопределяет чисто виртуальный метод IDrawable::show()
,
Чтобы переопределить метод, вам нужно точно определить сигнатуру функции в производном классе (разрешены только ко-вариантные типы возврата)
Сейчас у вас есть метод с именем show()
в производном классе, который шкуры метод по имени show()
в Базовом классе это не отменяет это. Поскольку вы не предоставляете определения для всех чисто виртуальных функций вашего класса Player
Компилятор справедливо говорит вам, что это абстрактный класс.
Возможно, что вместо переопределения чисто виртуальной функции одной из баз, вы объявили и определили функцию с немного другой сигнатурой, как показано ниже:
struct base {
virtual void foo(double d) = 0;
};
struct derived: base {
// does not override base::foo; possible subtle error
void foo(int i);
}
Возможно, вы захотите еще раз проверить свой код, просмотрев его. Если бы вы использовали C ++ 11, вы бы могли пометить свои функции override
ловить такие ошибки.
Абстрактный класс является абстрактным — то есть что-то не определено, а просто объявлено.
Вы должны определить все эти методы. Поскольку у меня нет объявлений для этих классов, я не могу посоветовать вам, какие методы вам не хватает.
В C ++ функция не является виртуальной, если она специально не написана:
virtual void move(Uint32 dTime);
чисто виртуальная функция определяется так:
virtual void move(Uint32 dTime) = 0;
«Интерфейсы», от которых вы наследуете (обратите внимание, что это множественное наследование.. C ++ не отличается интерфейсами от классов) имеет чисто виртуальные функции, которые вы не реализовали, что делает ваш класс абстрактным.
Конечно, это вызвано отсутствием переопределения чисто виртуальной функции — может быть, только небольшая разница в сигнатурах.
Я ожидаю, что компилятор скажет вам, какая функция все еще не переопределена, что-то вроде (vc9):
C2259: 'Player' : cannot instantiate abstract class
due to following members:
'void IUpdate::update(void)' : is abstract
virtualclass.cpp(3) : see declaration of 'IUpdate::update'
Если ваш компилятор не сообщил об этом, вы можете проверить, удалив унаследованный интерфейс один за другим.