Подтвердить что ты не робот

С++: невозможно объявить поле абстрактного типа

Я получаю эту ошибку при компиляции → не могу объявить поле 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.

4b9b3361

Ответ 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 также неверна, только статические константные члены класса могут быть инициализированы в объявлении класса.