2012-06-03 4 views
0

Я использую CodeBlocks, и у меня есть следующий код, который не компилируется.Виртуальная функция C++ не распознана

(Речь идет о ловушках некоторых C++, так что единственное, что я хочу спросить, почему он не компилируется)

Код выглядит следующим образом:

#include <iostream> 
using namespace std; 

class Shape 
{ 
     public: 
       Shape(); 
       virtual void reset(); 
     private: 
       int color; 
}; 

class Point : public Shape 
{ 
     private: 
     double a,b; 
}; 

void Shape::reset() 
{ 
     cout<<"Shape reset\n"; 
} 

void Point::reset() 
{ 
     Shape::reset(); 
     cout<<"Point reset"; 
} 

Shape::Shape() 
{ 
     reset(); 
} 

int main() 
{ 
     Shape s; 
     Point o; 
} 

Я получаю следующее сообщение об ошибке:

no `void Point::reset()' member function declared in class `Point' 

ответ

6

Вы должны добавить объявление функции для вашего Point тела класса:

class Point : public Shape 
{ 
public: 
    virtual void reset(); 
private: 
    double a,b; 
}; 

(virtual не является необходимым, поскольку он объявлен virtual в базовом классе. Но это полезно, чтобы добавить его в качестве напоминания)

+0

О, спасибо. Хотя это работает напрямую, расширяя Point from Shape, но теперь я вижу, что это не так. – delegat

+0

@delegat - Основная причина * почему * вам нужно объявить переопределения - это оптимизация вызовов. Компилятор часто знает точный тип объекта, и в этом случае он оптимизирует доступ VMT (вызывает метод напрямую, а не виртуально). Но если реализация «Point :: reset» была видна только в своем модуле компиляции, это привело бы к ошибочным вызовам «Shape :: reset» на объекты «Point» из других единиц компиляции, которые знали бы о «Point» но не о 'Point :: reset'. –

0

Он должен быть объявлен как это вместо:.

class Shape 
{ 
     public: 
       Shape(); 
       virtual void reset(){}; 
     private: 
       int color; 
}; 

Обратите внимание на скобки, так как виртуальная функция ничего не делает, то вы можете просто добавить скобки в объявлении , Поскольку это виртуальная функция, она предназначена для переопределения при наследовании базового класса. Поэтому нельзя называть Shape::reset() в вашей функции Point::reset(). Также в вашем классе Point вам необходимо переопределить новую функцию. Как это:

class Point : public Shape 
{ 
    public: 
     void reset(); 
} 

, то вы можете использовать функцию Point::reset.

Смежные вопросы