Почему невозможно определить не виртуальный метод как final в С++ 11?
Сегодня я был очень доволен, когда узнал, что С++ 11 теперь, наконец, знает ключевое слово final
. С его помощью вы можете легко определить целый класс как окончательный и даже один виртуальный метод. Но мне интересно, почему это невозможно для не виртуальных методов? Возьмем этот пример:
class A {
public:
void m1() { cout << "A::m1" << endl; };
virtual void m2() { cout << "A::m2" << endl; };
};
class B : public A {
public:
void m1() { cout << "B::m1" << endl; };
virtual void m2() { cout << "B::m2" << endl; };
};
Здесь я могу легко предотвратить B
от переопределения виртуального m2
, объявив A::m2
окончательным. Я хотел бы сделать то же самое с A::m1
, поэтому B
не может скрыть A:m1
с его собственной реализацией метода. но компилятор не принимает ключевое слово final
без virtual
. И мне интересно, есть ли причина, почему С++ 11 не позволяет этого, и если я неправильно понял что-то полностью. По моему мнению, имеет смысл определить не виртуальный метод как final, потому что я не объявлял его виртуальным, потому что я не хочу, чтобы другие все равно переопределяли/скрывали его (что теперь я могу обеспечить с помощью final
, но, к сожалению, только для виртуальных методов...)
Мне нравятся проекты классов, где все, кроме абстрактных методов, является окончательным. Похоже, это означает, что теперь я должен объявить все методы как virtual
, чтобы это сделать. Это хорошая идея или есть причины против этого? Для старых версий С++ я часто читаю, что это плохая идея объявить все методы виртуальными. Или, может быть, есть лучший способ предотвратить скрытие не виртуальных методов?
Ответы
Ответ 1
В соответствии со стандартом С++ 11 вам явно не разрешено делать это для функций. Соответствующий отрывок приведен в § 9.2/8:
Спецификатор virt-seq должен содержать не более одного из каждого видо-спецификатора. Спецификатор virt-seq должен появляться только в объявлении виртуальной функции-члена (10.3).
Спецификатор virt включает final
и override
.
Мое предположение заключается в том, что они полагали, что эти спецификаторы не имеют смысла использовать в не виртуальных функциях, поскольку по умолчанию не виртуальные функции final
, и они являются "окончательным переопределением", поскольку стандартные состояния в других разделы.
Похоже, это означает, что я должен объявить все методы как виртуальные, чтобы это сделать. Это хорошая идея или есть причины против этого?
Я рекомендую против него - поскольку наличие виртуальных функций оказывает различное влияние на код, который вам может не понадобиться. Например, теперь класс должен будет сохранить vtable и потерять статус POD. В целом это кажется неудачным, если вы просто хотите использовать ключевое слово final
.