Spec-Zone.ru › C++

final спецификатор (с C++11)

Указывает, что виртуальная функция виртуальная функция не может быть переопределена в производном классе, или что класс не может быть производным.

Синтаксис

При применении к член-функции идентификатор final появляется непосредственно после декларатора в синтаксисе объявления член-функции или определения член-функции внутри определения класса.

При применении к классу идентификатор final появляется в начале определения класса, непосредственно после имени класса.

декларатор virt-specifier-seq (необязательно) pure-specifier (необязательно) (1)
декларатор virt-specifier-seq (необязательно) function-body (2)
class-key attr (необязательно) class-head-name class-virt-specifier (необязательно) base-clause (необязательно) (3)
1) В объявлении член-функции final может появиться в virt-specifier-seq непосредственно после декларатора и перед pure-specifier, если используется.
2) В определении член-функции внутри определения класса final может появиться в virt-specifier-seq непосредственно после декларатора и перед function-body.
3) В определении класса final может появиться как class-virt-specifier непосредственно после имени класса, перед двоеточием, начинающим base-clause, если используется.

В случаях (1,2), virt-specifier-seq, если используется, это либо override или final, или final override или override final. В случае (3), единственное допустимое значение class-virt-specifier, если используется, это final.

Объяснение

При использовании в объявлении или определении виртуальной функции final спецификатор гарантирует, что функция является виртуальной и указывает, что она не может быть переопределена производными классами. В противном случае программа имеет ошибочную структуру (генерируется ошибка компиляции).

При использовании в определении класса final указывает, что этот класс не может появиться в base-specifier-list другого определения класса (другими словами, не может быть производным). В противном случае программа имеет ошибочную структуру (генерируется ошибка компиляции). final также может использоваться с определением объединения, в котором случае она не оказывает влияния (кроме как на результат std::is_final)(с C++14), так как объединения не могут быть производными.

final — это идентификатор со специальным значением при использовании в объявлении член-функции или заголовке класса. В других контекстах он не зарезервирован и может использоваться для именования объектов и функций.

Примечание

В последовательности следующих токенов:

  • одного из class, struct и union;
  • возможно квалифицированного идентификатора;
  • final;
  • одного из : и {,

третий токен final в последовательности всегда рассматривается как спецификатор, а не как идентификатор:

struct A;
struct A final {}; // OK, definition of struct A,
                   // not value-initialization of variable final
 
struct X
{
    struct C { constexpr operator int() { return 5; } };
    struct B final : C{}; // OK, definition of nested class B,
                          // not declaration of a bit-field member final
};
 
// Abnormal final usage.
 
struct final final // OK, definition of a struct named `final` from which
{                  // you cannot inherit
};
 
// struct final final {}; // Error: redefinition of `struct final`, NOT a
                          // definition of a variable `final` using an elaborated
                          // type specifier `struct final` followed by an
                          // aggregate initialization
 
// struct override : final {}; // Error: cannot derive from final base type;
                               // `override` in given context is a normal name
void foo()
{
    [[maybe_unused]]
    final final; // OK, declaration of a variable named `final` of type
                 // `struct final` 
}
 
struct final final; // OK, declaration of a variable named `final` of type
                    // `struct final` using an elaborated type specifier
int main()
{
}

Пример

struct Base
{
    virtual void foo();
};
 
struct A : Base
{
    void foo() final; // Base::foo is overridden and A::foo is the final override
    void bar() final; // Error: bar cannot be final as it is non-virtual
};
 
struct B final : A // struct B is final
{
    void foo() override; // Error: foo cannot be overridden as it is final in A
};
 
struct C : B {}; // Error: B is final

Возможный вывод:

main.cpp:9:10: error: 'void A::bar()' marked 'final', but is not virtual
    9 |     void bar() final; // Error: bar cannot be final as it is non-virtual
      |          ^~~
main.cpp:14:10: error: virtual function 'virtual void B::foo()' overriding final function
   14 |     void foo() override; // Error: foo cannot be overridden as it is final in A
      |          ^~~
main.cpp:8:10: note: overridden function is 'virtual void A::foo()'
    8 |     void foo() final; // Base::foo is overridden and A::foo is the final override
      |          ^~~
main.cpp:17:8: error: cannot derive from 'final' base 'B' in derived type 'C'
   17 | struct C : B // Error: B is final
      |

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2023):
    • 11 Классы [class]
    • 11.7.3 Виртуальные функции [class.virtual]
  • Стандарт C++20 (ISO/IEC 14882:2020):
    • 11 Классы [class]
    • 11.7.2 Виртуальные функции [class.virtual]
  • Стандарт C++17 (ISO/IEC 14882:2017):
    • 12 Классы [class]
    • 13.3 Виртуальные функции [class.virtual]
  • Стандарт C++14 (ISO/IEC 14882:2014):
    • 9 Классы [class]
    • 10.3 Виртуальные функции [class.virtual]
  • Стандарт C++11 (ISO/IEC 14882:2011):
    • 9 Классы [class]
    • 10.3 Виртуальные функции [class.virtual]

Отчёты об ошибках

Следующие поведенческие отчёты об ошибках были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применимо к Поведение, как опубликовано Корректное поведение
CWG 1318 C++11 определение класса, у которого final после имени класса и пустой список членов мог сделать final идентификатором final всегда является
спецификатором в этом случае

См. также

override спецификатор(C++11) явно объявляет, что метод переопределяет другой метод

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/final

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API