Почему невозможно определить не виртуальный метод как 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.