Рецепт `final`: опустить` virtual`? - PullRequest
       10

Рецепт `final`: опустить` virtual`?

3 голосов
/ 24 сентября 2011

Это правильный рецепт, чтобы сказать, что если я пишу final (в функцию-член), то не следует писать virtual?

В базовом классе final методы не имели бы смысла:

struct Driver {
    virtual void print();
};

Если добавить final к print(), это, в первую очередь, бросит вызов причине полиморфизма.Так что это было бы бесполезно (хотя и возможно).

Когда я наследую этот класс, я могу обнаружить ошибки с final, но только без virtual:

struct KeyboardDriver : public Driver {
    virtual void prynt() final;    // Oops: typo, but compiler-ok
};

struct MouseDriver : public Driver {
    void prynt() final;    // Error: Hooray, compiler found my typo
};

Дополнительные final для KeyboardDriver::prynt были законными.Поскольку final требует только, чтобы функция-член была virtual - компилятор пропускает это (FDIS 9.2p9).

Но когда я опускаю virtual, опечатка делает эту функцию не виртуальной- ничего не переопределяет, то есть нет виртуальной функции.Поэтому final без virtual служит в этом отношении той же цели, что и override.

Обновление: Правильно ли выполнен мой анализ?Включает ли функциональность final без virtual функцию override?

Ответы [ 4 ]

3 голосов
/ 24 сентября 2011

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

3 голосов
/ 24 сентября 2011

Это не то, для чего final. То, что вы ищете, это override.

struct Base { 
  virtual void print();
};

struct Derived : Base {
  void prynt() override; //compiler error
};

struct Good : Base {
  void print() override; //no compiler error
};

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

struct Best : Base {
  virtual void print() final override;
};
0 голосов
/ 24 сентября 2011

Является ли мой анализ правильным? Включает ли функциональность final без виртуальной функции функцию override?

Нет. Причина, по которой это была ошибка компилятора:

void prynt() final;    // Error: Hooray, compiler found my typo

Это потому, что final разрешено только для виртуальных функций. Компилятор жалуется, потому что вы использовали его в функции, которая не является виртуальной.

Нет ничего синтаксически неправильного в этой строке:

virtual void prynt() final;    // Oops: typo, but compiler-ok

Это может быть не то, что вы хотите, но это законный (и даже значимый, в зависимости от обстоятельств) код.

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

struct Driver {
    virtual void print();
};
struct MouseDriver : public Driver {
    void print();
};

Исключение virtual технически законно. Но лично я всегда чувствовал, что это дурной тон. Вы помещаете жизненно важную информацию (какие функции переопределяются) в другой класс. Я думаю, что было ошибкой даже позволять это компилировать.

Если вы хотите избежать этой проблемы, явно укажите virtual для всех виртуальных функций и используйте override в местах, где вы хотите создать новую функцию. Тогда это не будет правильно скомпилировано.

struct Driver {
    virtual void print();
};
struct MouseDriver : public Driver {
    virtual void print() override;
};
0 голосов
/ 24 сентября 2011

Не думаю, что это ошибка, это просто виртуальная функция, которую нельзя перегрузить.То же самое произошло бы, если бы функция была объявлена ​​виртуальной в родительском классе, поскольку виртуальные объявления наследуются.Было бы бессмысленно это запрещать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...