Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it not possible to define a non-virtual method as final in C++11?

Tags:

c++

c++11

Today I was pretty happy when I learned that C++11 now finally knowns the final keyword. With it you can easily define a whole class as final and even single virtual methods. But I wonder why this is not possible for non-virtual methods? Let's take this example:

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; };
};

Here I can easily prevent B from overriding the virtual m2 by declaring A::m2 as final. I would like to do the same with A::m1 so B can't hide A:m1 with it's own implementation of the method. but the compiler doesn't accept the final keyword without virtual. And I wonder if there is a reason why C++11 doesn't allow this and if I misunderstood something completely. In my opinion it makes perfectly sense to define a non-virtual method as final because I didn't declare it as virtual because I don't want others to override/hide it anyway (Which I can now enforce with final but unfortunately only for virtual methods...)

I like class designs where everything except abstract methods are final. It looks like this means I have to declare all methods as virtual now to be able to do that. Is that a good idea or are there reasons against it? For older C++ versions I often read that is a bad idea to declare all methods as virtual. Or maybe there is a better way to prevent hiding non-virtual methods?

like image 752
kayahr Avatar asked Jul 03 '14 05:07

kayahr


1 Answers

According to the C++11 standard, you are explicitly not allowed to do so for functions. The relevant passage is under § 9.2/8:

A virt-specifier-seq shall contain at most one of each virt-specifier. A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).

A virt-specifier includes final and override.

My guess is that they thought that these specifiers didn't make sense to be used in non-virtual functions since non-virtual functions are final by default and they are the "final overrider" as the standard states in other sections.

It looks like this means I have to declare all methods as virtual now to be able to do that. Is that a good idea or are there reasons against it?

I recommend against it -- as having virtual functions has different effects on the code which you may not want. For example, the class will now have to keep a vtable and lose its POD status. Overall it seems like a bad move if you just want to use the final keyword.

like image 163
Rapptz Avatar answered Oct 13 '22 23:10

Rapptz