| 
 Ключевое слово final [1] указывает, что виртуальная функция [2] не может быть переопределена в производном классе, или что от этого класса не может быть наследования. 
Когда ключевое слово final применяется к функции-члену класса, оно появляется сразу после декларатора функции внутри определения класса, или после определения функции внутри определения класса. 
Когда ключевое слово final применяется к классу, оно появляется в начале определения класса, сразу после имени класса. 
декларатор virt-spec-seq(*) pure-spec(*)                             (1) декларатор virt-spec-seq(*) тело-функции                             (2) class-key attr(*) class-head-name class-virt-spec(*) base-clause(*)  (3) 
(1) В декларации функции-члена класса внутри определения класса final может появляться в virt-spec-seq сразу после декларатора и перед pure-spec, если это используется. (2) В определении функции-члена класса внутри определения класса final может появляться в virt-spec-seq сразу после декларатора и перед телом функции. (3) В определении класса final может появляться в качестве class-virt-spec сразу после имени класса, непосредственно перед двоеточием, с которого начинается base-clause, если это используется. 
Примечание (*): эта часть не обязательна (опциональна). 
В случаях (1,2), virt-spec-seq, если используется, будет либо override [4], либо final, либо final override, либо override final. В случае (3), допускается только значение final в качестве class-virt-spec, если это используется. 
[В чем смысл final?] 
Когда ключевое слово final используется в декларации или определении виртуальной функции, оно гарантирует, что функция виртуальная, и указывает, что она не может быть переопределена в производных классах. Иначе в программе ошибка (при компиляции генерируется сообщение об ошибке). 
Когда ключевое слово final используется в определении класса, оно указывает, что этот класс не может появляться в списке базовых классов определения другого класса (другими словами, final-класс не может наследоваться). Иначе в программе ошибка (при компиляции генерируется сообщение об ошибке). Ключевое слово final также может использоваться в определении объединения (union), в этом случае final не оказывает никакого эффекта (кроме как влияния на результат std::is_final, см. стандарт C++14), поскольку объединения не могут наследоваться. 
Слово final получает свой специальный смысл, когда используется в декларации функции-члена класса, или в заголовке класса. В других контекстах final не резервируется как ключевое слово, и может использоваться для именования объектов и функций (что конечно добавляет путаницы и так сложный синтаксис C++). 
Пример: 
struct Base
{
   virtual void foo();
};
 
struct A : Base
{
   void foo() final; // Base::foo переопределена и A::foo это конечный переопределитель
   void bar() final; // Ошибка: bar не может быть final, поскольку он не виртуальный
};
 
struct B final : A   // struct B обладает свойством final
{
   void foo() override; // Ошибка: foo не может быть переопределена, поскольку
                        // в A она определена как final.
};
 
struct C : B         // Ошибка: B обладает свойством final
{
};
 
[Ссылки] 
1. final specifier (since C++11) site:cppreference.com. 2. C++: ключевое слово virtual. 3. C++: производные классы (наследование). 4. C++: спецификатор override.  |