У меня есть базовый класс с виртуальной функцией, и я хочу переопределить эту функцию в производном классе. Есть ли способ заставить компилятор проверить, действительно ли функция, объявленная в производном классе, переопределяет функцию в базовом классе? Я хотел бы добавить какой-нибудь макрос или что-то, что гарантирует, что я случайно не объявил новую функцию, вместо того, чтобы переопределить старую.
Вот пример:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Здесь parent::handle_event()
вызывается вместо child::handle_event()
, потому что дочерний метод пропускает const
объявление и поэтому объявляет новый метод. Это также может быть опечатка в имени функции или незначительное различие в типах параметров. Это также может легко произойти, если интерфейс базового класса изменится и где-то не был обновлен какой-либо производный класс, чтобы отразить это изменение.
Есть ли способ избежать этой проблемы, могу ли я каким-то образом сказать компилятору или другому инструменту проверить это за меня? Любые полезные флаги компилятора (желательно для g ++)? Как избежать этих проблем?
источник
Ответы:
Начиная с g ++ 4.7, он понимает новое
override
ключевое слово C ++ 11 :источник
override
необходимо использовать @ h9uest . Встроенная реализация - это и определение, и реализация, так что это нормально.Что-то вроде
override
ключевого слова C # не является частью C ++.В gcc
-Woverloaded-virtual
предостерегает от сокрытия виртуальной функции базового класса функцией с тем же именем, но с достаточно другой подписью, чтобы она не переопределяла ее. Однако это не защитит вас от невозможности переопределить функцию из-за неправильного написания самого имени функции.источник
override
создает ключевого слова в C ++; это может означать, что вы используете что-то, что может скомпилировать некорректный исходный код C ++. ;)override
функциональность стиля C # ; У меня редко возникали проблемы с неудачными переопределениями, и их было относительно легко диагностировать и исправить. Думаю, я не согласен с тем, что пользователи VC ++ должны его использовать. Я бы предпочел, чтобы C ++ выглядел как C ++ на всех платформах, даже если один конкретный проект не нужно переносить. Стоит отметить , что C ++ 0x будет иметь[[base_check]]
,[[override]]
и[[hiding]]
атрибуты , так что вы можете выбрать , чтобы отменить проверку , если это необходимо.override
в ключевое слово, похоже, он сделал . Ну, не правильное ключевое слово, а специальный идентификатор в C ++ 11. Microsoftoverride
Насколько я знаю, нельзя просто сделать это абстрактным?
Я думал, что читал на www.parashift.com, что вы действительно можете реализовать абстрактный метод. Что имеет смысл лично для меня, единственное, что он делает, это заставляет подклассы реализовывать его, никто ничего не сказал о том, что ему не разрешено иметь саму реализацию.
источник
BaseClass::method()
вызов базового метода (скажем ) в производной реализации (скажемDerivedClass::method()
), например, для значения по умолчанию.В MSVC вы можете использовать
override
ключевое слово CLR, даже если вы не компилируете для CLR.В g ++ нет прямого способа обеспечить это во всех случаях; другие люди дали хорошие ответы о том, как улавливать различия сигнатур с помощью
-Woverloaded-virtual
. В будущей версии кто-то может добавить подобный__attribute__ ((override))
или эквивалентный синтаксис с использованием синтаксиса C ++ 0x.источник
В MSVC ++ вы можете использовать ключевое слово
override
override
работает как с машинным кодом, так и с кодом CLR в MSVC ++.источник
Сделайте функцию абстрактной, чтобы у производных классов не было другого выбора, кроме как переопределить ее.
@Ray Ваш код недействителен.
В абстрактных функциях не могут быть встроены тела. Он должен быть изменен, чтобы стать
источник
Я бы посоветовал немного изменить вашу логику. Это может сработать, а может и не сработать, в зависимости от того, что вам нужно сделать.
handle_event () может по-прежнему выполнять «скучный код по умолчанию», но вместо того, чтобы быть виртуальным, в точке, где вы хотите, чтобы он выполнял «новый захватывающий код», базовый класс должен вызывать абстрактный метод (т.е. метод, который должен быть переопределен) который будет предоставлен вашим потомком.
РЕДАКТИРОВАТЬ: И если вы позже решите, что некоторые из ваших потомков классов не должны предоставлять «новый захватывающий код», вы можете изменить абстрактное на виртуальное и предоставить пустую реализацию базового класса этой «вставленной» функциональности.
источник
У вашего компилятора может быть предупреждение, которое он может сгенерировать, если функция базового класса станет скрытой. Если это так, включите его. Это отловит константные конфликты и различия в списках параметров. К сожалению, это не обнаружит орфографическую ошибку.
Например, это предупреждение C4263 в Microsoft Visual C ++.
источник
override
Ключевое слово C ++ 11 при использовании с объявлением функции внутри производного класса заставляет компилятор проверять, действительно ли объявленная функция заменяет некоторую функцию базового класса. В противном случае компилятор выдаст ошибку.Следовательно, вы можете использовать
override
спецификатор для обеспечения динамического полиморфизма (переопределения функции).источник