When adding the final qualifier, we forbid overriding the method in the base class. Then why do we need to create a virtual method in the base class, if we can leave it normal? What else is a virtual modifier used for?

 class Base { public: virtual void doSomething(int x) final; }; 

For example, like this:

 class Base { public: void doSomething(int x); }; 

3 answers 3

Such a combination of virtual and final will be formally correct, but in fact meaningless. So the question here is rather to the author of the code: why did they declare such a method?

If you aim to push the ears behind the excuses for such use, then a possible reason could be the desire to formally make the class polymorphic . (For example, I wanted for some of my goals that dynamic_cast<void *> worked with Base * type pointers, and the Base * class, unfortunately, is not polymorphic for me.) To do this, create at least one virtual method in it, even if the virtuality of this method is in fact "no one needs anymore." Traditionally, in such situations virtual make destructor. But as a strange alternative, you can consider such a "fictitious" virtuality, as in your example.

PS Do not call non-virtual methods "static". The term static method in C ++ is already reserved and is used for very different purposes.

    The c++11 final standard is defined as virt-specifier , so it does not make sense for non-virtual methods and generates an error:

     marked final, but is not virtual 

    However, as a rule, final not used in the definition of the virtual methods of the base class.
    final used in successor classes that override the method to prevent further changes to the method implementation.
    Therefore, final often used with the override specifier.

      The final usually not used in the base class (see the vp_arth response).

      This modifier is used to prohibit the redefinition of a virtual function in the derived class, therefore, it is usually used when inheriting more than 2 levels.

       struct A { virtual void foo() { std::cout << "I'm A!\n"; } }; struct B : A { virtual void foo() override final { std::cout << "I'm B!\n"; } }; struct C : B { virtual void foo() override { std::cout << "I'm C!\n"; } // <- запрещено, ошибка времени компиляции }; 

      PS In the heirs, the virtual does not carry a semantic load, but left it for clarity.

      • one
        Why is it pointless? How else to prohibit override the behavior of the method in the second heir? Non-virtual functions do not have such a mechanism - vp_arth
      • @vp_arth reread your answer, I understand, I agree. Corrected his. - int3