Ссылка на ответ Джима, который был превосходным, кстати, описывает только то, когда и где использовать директивы. Другая часть ответа - зачем они нужны? Многие языки прекрасно обходятся без них, верно? При разработке аспектов языка Delphi Object Pascal ООП (объектно-ориентированное программирование) было в мейнстриме в течение нескольких лет. В течение этого времени было замечено, что использование многих языков, в которых были приняты эти концепции (Turbo Pascal, C ++ и т. Д.) Для разработки прикладных сред, страдало от того, что я назвал проблемой «версии 2.».
Предположим, вы разработали потрясающую среду, используя язык X, и выпустили ее как версию 1. Ваши пользователи были в восторге от всего, что он мог сделать, и он стал активно использоваться. Встретившись с успехом, вы решили выпустить версию 2 с еще большей удивительностью. Вы специально убедились, что он полностью обратно совместим. Внезапно ваши пользователи начали сообщать о странном поведении. Их собственные виртуальные методы вызывались в странные времена. Многие сообщили, что их старый код не будет компилироваться с новой версией. Странный. Все те же объекты, методы и функциональность все еще остались. Все, что вы сделали, это добавили несколько виртуальных методов к некоторым базовым классам, несколько новых типов объектов и некоторые новые дополнительные функции. Что случилось?
Директивы override и reintroduce служат для устранения этой проблемы, требуя, чтобы для фактического override виртуального метода вы использовали директиву override вместо виртуальной директивы. Если вам случится представить свой собственный виртуальный метод, имя которого совпадает с именем одного из виртуальных методов ваших предков, компилятор теперь предупредит вас, но все равно будет поступать правильно. В этом случае повторное введение не только подавляет это предупреждение, но и служит для документирования в источнике, который вы намеревались сделать.
Без директив переопределения и повторного ввода вы не сможете постоянно развивать свою среду, не опасаясь взломать всех своих пользователей. И если бы вашим пользователям приходилось вносить огромные изменения каждый раз, когда выпускается новая версия, они не хотели бы принимать новую версию. Наконец, использование «переопределения» также позволяет конструктору каркасов изменять тип виртуального в предках, не нарушая пользовательский код. Например, в Delphi многие методы помечены как «динамические», что является формой поиска полиморфизма на основе таблицы во время выполнения. Он работает не так быстро, как обычный виртуальный, поэтому он обычно используется для методов, которые редко переопределяются и / или являются реакциями на действия пользователя, когда дополнительные издержки никогда не замечаются. Предположим, что в V1 фреймворка метод был помечен как «динамический», но на практике он был переопределен и вызван больше, чем вы предполагали. В V2 вы можете изменить его на «виртуальный», не опасаясь взлома пользовательского кода.
Язык Object Pascal в Delphi - не единственный язык, который распознает эту проблему. C # требует использования директивы override по той же самой причине. Комитет по стандартам C ++ наконец-то осознает проблему и модифицирует язык для ее поддержки ... вроде. В C ++, если имя метода и список параметров совпадают с виртуальным предком, это переопределение (даже если вы не говорите «виртуальный» для потомка!). Для грядущего нового стандарта C ++, если вы укажете «virtual» и сигнатуры не будут совпадать, тогда это новый виртуальный метод, представленный в текущем классе. Если есть совпадение подписи с предком и автор не не намеревался переопределить, то ключевое слово "new" используется, чтобы сообщить компилятору, что это new virtual для этот класс.