С++: невозможно объявить поле абстрактного типа
Я получаю эту ошибку при компиляции → не могу объявить поле M1:: sc абстрактным типом I1, потому что следующие виртуальные функции чисты в I1. Пожалуйста, помогите.
class I1
{
public:
virtual void a(int dir) = 0;
virtual void b() = 0;
virtual void c() = 0;
void a(int dir) {
....
}
void b() {
....
}
void c() {
....
}
};
class I2 : public I1
{
public:
void a(int dir) {
....
}
void b() {
....
}
void c() {
....
}
};
class M1 : public G1
{
protected:
I1 sc;
public:
int dir = 4;
sc.a(dir);
};
Полный код можно найти на http://pastebin.com/PFrMTJuF.
Ответы
Ответ 1
Абстрактные классы не могут быть созданы, но вы просите компилятор сделать это, вставив экземпляр I1
в каждый экземпляр M1
.
Вы можете обойти это, слегка изменив свой дизайн и введя указатель (или интеллектуальный указатель, если вы можете использовать их) вместо экземпляра I1
:
class M1 : public G1
{
protected:
I1 *sc;
public:
M1(I1 *sc_) {
sc = sc_;
}
void foo() {
int dir = 4;
sc->a(dir);
}
};
EDIT:. Прочитав ваш код, я считаю, что самый простой и самый чистый способ решить вашу проблему - передать текущую комнату методу Execute()
вашей команды, например. что-то вроде:
class ICommand
{
public:
virtual ~ICommand()
{
}
virtual void Execute(Room *room) = 0;
};
class MoveCommand : public GameCommand
{
public:
MoveCommand()
{
}
void Execute(Room *room)
{
// Do something with `room`...
}
};
void Game::HandleInput()
{
// Read command from user and generate a command object from it.
ICommand *pCommand = ParseCommand(Input::ReadCommand());
if (pCommand) {
pCommand->Execute(GetCurrentRoom()); // Pass current room to command.
delete pCommand;
}
}
Ответ 2
I1
- абстрактный класс, поскольку он имеет чисто виртуальные функции (= функции без определения).
Вы не можете создавать экземпляры абстрактных классов (потому что как они будут работать?!), поэтому объявление, такое как I1 a
, не работает.
После вашего редактирования вопроса кажется, что I1
не должен быть абстрактным классом, поскольку вы предоставили определения для методов. Если это так, просто удалите = 0
после объявлений вашего метода, чтобы заставить код работать.
Ответ 3
Вы не можете создать экземпляр для абстрактного класса (класс, который имеет одну или несколько чистых виртуальных функций).
Также есть еще одна проблема. Что вы хотите, чтобы компилятор выполнял при вызове функции sc.a(dir)
в декларации класса? Строка dir = 4
также неверна, только статические константные члены класса могут быть инициализированы в объявлении класса.