2016-02-18 1 views
2

Это несколько классов моей программы на C++.Проблема на C++: не может выделить объект абстрактного типа, но почему?

ElementTerrain.h:

#ifndef ELEMENTTERRAIN_H_ 
#define ELEMENTTERRAIN_H_ 

#include <iostream> 
#include <string> 

using namespace std; 

class ElementTerrain { 
public: 
    virtual ~ElementTerrain(){} 
    virtual string getElement() const = 0; 
    virtual string getType() const = 0; 
    virtual int getStock() const = 0; 
}; 

#endif /* ELEMENTTERRAIN_H_ */ 

Mine.h:

#ifndef MINE_H_ 
#define MINE_H_ 

#include "ElementTerrain.h" 

using namespace std; 

class Mine : public ElementTerrain{ 
public: 
    Mine(); 
    Mine(bool, bool, int); 
    Mine(const Mine &); 
    virtual ~Mine(); 

    string getElement(){ 
      return "Mine"; 
     } 

    string getType(){ 
     if(this->ur == true){ 
      return "UR";} 
     if(this->plu == true){ 
      return "PLU";} 
     return "None"; 
    } 

    int getStock() { 
     return stock; 
    } 

    void setStock(int stock) { 
     this->stock = stock; 
    } 

    bool isUr() { 
     return ur; 
    } 

    bool isPlu() { 
     return plu; 
    } 

private : 
    bool ur; 
    bool plu; 
    int stock; 
}; 

#endif /* MINE_H_ */ 

Mine.cpp:

#include "Mine.h" 

using namespace std; 

Mine::Mine() { 
    this->ur = false; 
    this->plu = false; 
    this->stock = 0; 
} 

Mine::Mine(bool ur, bool plu, int stock){ 
    this->ur=ur; 
    this->plu=plu; 
    this->stock = stock; 
} 

Mine::Mine(const Mine &m){ 
    this->ur=m.ur; 
    this->plu=m.plu; 
    this->stock = m.stock; 
} 

Mine::~Mine() { 
    // TODO Auto-generated destructor stub 
} 

И это файл, в котором я имею ошибки:

#include "ElementRobot.h" 
#include "Mine.h" 
#include <iostream> 

using namespace std; 

bool ElementRobot::RecolteMine(Terrain& t, ElementRobot& r) { 
    if(t.plateau[x][y]->getElem() != NULL){ 
      if(t.plateau[x][y]->getElem()->getElement() == "Mine"){ 
       Mine *m = new Mine(); 
       if(m.getType() == r.getType() && m.getStock()>0 && r.stock<r.cap){ 
        m.setStock(m.getStock()-1); 
        t.plateau[x][y]->setElem((Mine) t.plateau[x][y]->getElem()); 
        return true; 
       } 

       if(m.getType() == r.getType() && m.getStock()==0){ 
        cout << "Les stocks de cette mine sont épuisés.\n" << endl; 
       } 

       if(r.stock==r.cap){ 
        cout << "Votre robot ne peut pas porter plus de minerai.\n" << endl; 
       } 

       if(m.getType() != r.getType()){ 
        cout << "Ce robot n'est pas adapté à cette mine.\n" << endl; 
       } 
      }} 
      return false; 
} 

Я хочу создать объект типа Mine с помощью конструктора копирования (здесь я попробовал только со стандартным конструктором), но он говорит, что я не могу выделить объект абстрактного типа Mine, хотя в моем классе Mine нет чистого виртуальный метод. Я начинаю с C++, и я не понимаю свою ошибку. Я ничего не мог найти в Интернете.

ответ

9

Подписи функций-членов Mine не соответствуют характеристикам базового класса (отсутствуют квалификаторы const). Поэтому у вас нет переопределенных, но перегружены и Mine продолжает быть абстрактным и несовместимым.

Это практически как с этого:

class Mine { 
public: 
    // this has to be implemented by deriving classes 
    virtual string getElement() const = 0; 

    // this is a separate overload 
    string getElement() { ... }; 
}; 

Решение: Закрепить подписи:

string getElement() const { ... } 
//     ^^^^^ 

и так далее ...

11 C++ в override ключевых слов поможет вы очень - отметили бы, что не существует константной функции виртуального участника с именем getElement для переопределения.

+1

Большое спасибо, это очень полезно, я не рассматривал разницу между перегруженными и перегруженными. Теперь я буду более осторожен. – BlaCkOmN

2

Вы забыли const в объявлениях функций.

Посмотрите здесь:

class ElementTerrain { 
public: 
    virtual ~ElementTerrain(){} 
    virtual string getElement() const = 0; // <- notice 'const' 
    virtual string getType() const = 0; // <- notice 'const' 
    virtual int getStock() const = 0; // <- notice 'const' 
}; 

Так что добавьте const ключевое слово getElement, getType и getStock функций.

class Mine : public ElementTerrain{ 
public: 
    Mine(); 
    Mine(bool, bool, int); 
    Mine(const Mine &); 
    virtual ~Mine(); 

    string getElement() const{ // notice 'const' is added here.. 
      return "Mine"; 
     } 

    string getType() const{ // notice 'const' is added here.. 
     if(this->ur == true){ 
      return "UR";} 
     if(this->plu == true){ 
      return "PLU";} 
     return "None"; 
    } 

    int getStock() const{ // notice 'const' is added here.. 
     return stock; 
    } 

    void setStock(int stock) { 
     this->stock = stock; 
    } 

    bool isUr() { 
     return ur; 
    } 

    bool isPlu() { 
     return plu; 
    } 

private : 
    bool ur; 
    bool plu; 
    int stock; 

}; 

Кроме того, если вы хотите избавиться, если эта ошибка навсегда я советую вам добавить override C++ 11 ключевое слово после объявления функции, если вы хотите, чтобы переопределить функции, как это:

int getStock() const override{ 
    return stock; 
} 

В этом в случае, если ваш компилятор C++ проверяет, существует ли такая виртуальная функция в любом суперклассе и поднимет ошибку компиляции, если она не существует.