Подтвердить что ты не робот

Существуют ли тонкости использования как виртуальных, так и переопределяющих ключевых слов в С++ 11?

Возможно ли использовать функции virtual и override для функции в С++? Означает ли это вас для двусмысленности при перегрузке?

Очевидно, что virtual должен использоваться в базовом классе, и было бы глупо не использовать override в производном классе, но действительно ли проблематично использовать virtual с override в производном классе?

Попытка определить, является ли это проблемой стиля или правильности.

Пример:

class Widget {
  virtual void transmogrify() = 0;
}

class Gadget : public Widget {
  virtual void transmogrify() override {}
}
4b9b3361

Ответ 1

Позднее, но это C++ основное руководство здесь кажется уместным:

C.128: Виртуальные функции должны указывать точно один из virtual, override или final

Reason

читаемость. Обнаружение ошибок. Написание явных virtual, override или final является самодокументированным и позволяет компилятору обнаруживать несоответствие типов и/или имен между базовыми и производными классами. Однако написание более одного из этих трех излишне и является потенциальным источником ошибок.

Это просто и понятно:

  • virtual означает точно и только "это новая виртуальная функция".
  • override означает точно и только "это не окончательный переопределитель".
  • final означает точно и только "это окончательное переопределение".

Ответ 2

Ключевое слово virtual не действует, когда вы переопределяете. Выведенная функция, которая является сигнатурным совпадением для виртуальной функции, определенной в базовом классе, переопределит базовое определение, и переопределение будет введено в таблицу vtable, независимо от того, используется ли ключевое слово virtual в производном классе или нет.

Поскольку ключевое слово override вызывает ошибку компиляции, если переопределение не происходит, ключевое слово virtual бесполезно в комбинации.

Вот, у меня есть cheatsheet:

| Keyword used | Matching virtual function in base class | Result                   |
|--------------|-----------------------------------------|--------------------------|
| Neither      | No                                      | New non-virtual function |
| Neither      | Yes                                     | Override                 |
| virtual      | No                                      | New virtual function     |
| virtual      | Yes                                     | Override                 |
| override     | No                                      | Compile error            |
| override     | Yes                                     | Override                 |
| Both         | No                                      | Compile error            |
| Both         | Yes                                     | Override                 |

Ответ 3

В вашем примере вы говорите две разные, но важные вещи о методе Gadget transmogrify

virtual - если класс происходит от Gadget, то функция transmogrify будет считаться виртуальной производным классом

override - класс Gadget явно переопределяет базовый класс Widget версии transmogrify.

Два ключевых произведения ортогональны и не влияют друг на друга. Самое приятное в ключе override заключается в том, что он указывает компилятору, что вы пытаетесь переопределить унаследованную виртуальную функцию. Если вы допустили ошибку в сопоставлении сигнатуры функции функции в базовом классе, она не будет компилироваться, поскольку она должна переопределить унаследованную функцию, если она объявлена ​​как override