C ++: Невозможно объявить поле абстрактного типа - PullRequest
20 голосов
/ 28 ноября 2010

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

Ответы [ 3 ]

15 голосов
/ 28 ноября 2010

Абстрактные классы не могут быть созданы, но вы просите компилятор сделать это путем встраивания экземпляра I1 в каждый экземпляр M1.

Вы можете обойти это, немного изменив свой дизайн и вставив указатель (или умный указатель, если вы можете их использовать) вместо экземпляра I1:

class M1 : public G1
{
protected:
    I1 *sc;
public:
    M1(I1 *sc_) {
        sc = sc_;
    }
    void foo() {
        int dir = 4;
        sc->a(dir);
    }
};

РЕДАКТИРОВАТЬ: После прочтения вашего кода, я думаю, что самый простой и чистый способ решения вашей проблемы - передать текущую комнату методу 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;
    }
}
7 голосов
/ 28 ноября 2010

I1 - абстрактный класс, потому что он имеет чисто виртуальные функции (= функции без определения).

Вы не можете создавать экземпляры абстрактных классов (потому что, как они будут работать ?!), поэтому объявлениенапример, I1 a не работает.

После редактирования вопроса кажется, что I1 не должен быть абстрактным классом, поскольку вы предоставили определения для методов.Если это так, просто удалите = 0 после объявления метода, чтобы код работал.

1 голос
/ 28 ноября 2010

Вы не можете создать экземпляр для абстрактного класса (класса, который имеет одну или несколько чисто виртуальных функций).Также есть другая проблема.Что вы хотите, чтобы компилятор делал, когда вы вызываете функцию sc.a(dir) в объявлении класса?Строка dir = 4 также неверна, только статические члены класса const могут быть инициализированы в объявлении класса.

...