What is the opposite of the C ++ specifier `override` /` final`?

  • In C ++ 11, an override specifier protects against overriding a supposed virtual base function (because the signatures do not match).
  • final specifier protects against inadvertently overriding functions in a derived class.

=> Is there a specifier (something like, perhaps, first or no_override ) that protects against overriding an unknown base function?

I would like to get a compiler error when a virtual function was added to the base class with the same signature as the existing virtual function in the derived class.


EDIT 4 . So that this question is simple and answers the questions, here again

original pseudo code

  • abstract class B : A has private: virtual void fooHasBeenDone() = 0;
  • class C : B implements private: virtual void fooHasBeenDone() override { react(); } private: virtual void fooHasBeenDone() override { react(); }
  • Now class A gets a new private: virtual void fooHasBeenDone();
  • But the new A::foo may be different from the original B::foo .

and concrete example

  • abstract class B : A has virtual void showPath() = 0; measure PainterPath
  • class C : B implements virtual void showPath() override { mPath.setVisible(); } virtual void showPath() override { mPath.setVisible(); }
  • Now class A gets a new virtual void showPath(); , meaning the path to the file
  • Now, when A calls showPath (), B shows PainterPath instead of some file path.

Of course, this is wrong, and I have to rename B::showPath() to B::showPainterPath() and implement B::showPath() override . I would just like to get information from the compiler.


Here is a compilation example of the real world:

 #include <iostream> #define A_WITH_SHOWPATH class A { #ifdef A_WITH_SHOWPATH public: void setPath(std::string const &filepath) { std::cout << "File path set to '" << filepath << "'. Display it:\n"; showPath(); } // to be called from outside, supposed to display file path virtual void showPath() { std::cout << "Displaying not implemented.\n"; } #else // has no showPath() function #endif }; class B : public A { public: virtual void showPath() = 0; // to be called from outside }; class C1 : public B { public: virtual void showPath() override { std::cout << "C1 showing painter path as graphic\n"; } }; class C2 : public B { public: virtual void showPath() override { std::cout << "C2 showing painter path as widget\n"; } }; int main() { B* b1 = new C1(); B* b2 = new C2(); std::cout << "Should say 'C1 showing painter path as graphic':\n"; b1->showPath(); std::cout << "---------------------------\n"; std::cout << "Should say 'C2 showing painter path as widget':\n"; b2->showPath(); std::cout << "---------------------------\n"; #ifdef A_WITH_SHOWPATH std::cout << "Should give compiler warning\n or say \"File path set to 'Test'. Display it:\"\n and \"Displaying not implemented.\",\n but not \"C1 showing painter path as graphic\":\n"; b1->setPath("Test"); std::cout << "# Calling setPath(\"Test\") on a B pointer now also displays the\n# PainterPath, which is not the intended behavior.\n"; std::cout << "# The setPath() function in B should be marked to never override\n# any function from the base class.\n"; std::cout << "---------------------------\n"; #endif return 0; } 

Run it and look at the text output.


For reference, an older example with a specific use case (an instance of PainterPath):

https://ideone.com/6q0cPD (link may have expired)

+8
c ++ inheritance c ++ 11 class-hierarchy modifiers
source share
4 answers

This answer is a wiki community because it combines all the other answers. Please support a specific answer that was useful to you, as well as this one.

  • No, there is no specifier like first or no_override . (answer)
  • You should use the override specifier as often as possible.
    Qt has a macro Q_DECL_OVERRIDE , which expands to override , if available.
    If they are not available, at least mark each override function with comments.
  • If you do this, there are compiler flags that warn of no override :
    Clang now has -Winconsistent-missing-override , and the new GCC has -Wsuggest-override . "
    I don't know which VS2012 flag is for this. Feel free to edit.
  • You can imitate the desired behavior by adding a “secret” that the base class cannot know. (answer)
    This is useful in very specific use cases, but generally violates the concept of virtuality (see Comments on other answers).
  • If you do not own the base class and have a conflict (for example, a compiler warning), you will need to rename your virtual function in all derived classes.
  • If you own a base class,, you can temporarily add final to any new virtual function. (answer)
    After compiling the code without errors, you know that no function of this name and signature exists in any derived class, and you can delete final again.

... I think I'll start marking the first virtual functions as DECL_FIRST . Perhaps in the future there will be a compiler-independent way of checking this.

+2
source share

Not. Not.

Adding a virtual function to a base class that has the same signature as the virtual function in the child class cannot destroy any existing functionality unless you add that the virtual function turns the base class into a polymorphic type . Thus, normally, it is benign, and the purest will argue, adding language features to protect against this would be pretty pointless.

(Of course, you could mark your new final function only to verify that the function of the child class is not going to compress it.)

Your only option is to resort to code analysis tools.

(Please note that VS2012 does not implement or even does not require the implementation of the C ++ 11 standard, although it does have some of them.)

+2
source share

A specifier object of type first or no_override does not exist as such. Probably because it can create confusion. However, this can be trivially achieved by changing the approach.

You should add a new method to the base class with final specifier . This will help to get a compiler error for any matching signatures. Because it will make subsequent method signatures of the derived class automatically as "first" of its kind. Later, the final keyword can be removed , as it is intended only for “first-hand verification”.

Putting and deleting the final keyword after the recently added base method is similar to compiling a binary file with the debug parameter ( g++ -g ), which helps to fix the error. In production, this debugging option is removed for optimization.

In your example:

 class A {}; // no method, no worry class B { public: virtual void showPath() = 0; // ok }; ... 

Now you accidentally add a similar method to A , which leads to an error:

 class A { public: virtual void showPath() final; // same signature by chance // remove the `final` specifier once the signature is negotiated }; class B { public: virtual void showPath() = 0; // ERROR }; 

So, the signatures between the new A::showPath() and the existing B::showPath() must be consistent and then continue by removing the final specifier.

+2
source share

C ++ doesn't seem to provide such facilities out of the box. But you can mimic this as follows:

 template<class Base> class Derived : public Base { private: struct DontOverride {}; public: // This function will never override a function from Base void foo(DontOverride dummy = DontOverride()) { } }; 

If you intend to introduce a new virtual function, follow these steps:

 template<class Base> class Derived : public Base { protected: struct NewVirtualFunction {}; public: // This function will never override a function from Base // but can be overriden by subclasses of Derived virtual void foo(NewVirtualFunction dummy = NewVirtualFunction()) { } }; 
+1
source share

All Articles