0

Is there a good reason why a virtual function is virtual by default in a derived class and it is not even possible to remove virtuality completely in the derived function?

The reason why I want this behaviour is the same reason I do not want every function to be virtual by default. The compiler might generate vtables which costs performance.

There should be a vtable for the base class (I want polymorphism there), but no vtable for the derived class (I do not want polymorphism there, why should I want that, only because it derives of a class with polymorphism?).

The problem I want to solve is to better understand virtual functions. I just do not get this design decision and wonder if there is any reason for this.

Henk
  • 826
  • 3
  • 14
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/227824/discussion-on-question-by-henk-why-is-a-virtual-function-in-a-derived-class-also). – Machavity Jan 26 '21 at 01:15

3 Answers3

3

A vtable for a particular class has pointers to the virtual functions for that particular class. A vtable for a base class does not point to the virtual functions overridden by a derived class. There could be many derived classes, and the base class knows about precisely zero of them, so there's no way to have pointers to those functions. Only a derived class's vtable may have pointers to the derived class's functions.

The point of a virtual function is that, if you convert an object of the derived class to a base class pointer/reference, then calling any virtual function declared in the base class must call the most derived class's version of that function for that object. The only way to do that is if the vtable for that object has a pointer to the most-derived-class's version of that function. And that can only happen if the vtable for that object is the derived class's vtable.

That's how vtable's work.

If the derived class doesn't have a vtable of its own, which points to its own overridden member functions rather than the base class functions, then virtual dispatch can't work.

I do not want polymorphism there, why should I want that, only because it derives of a class with polymorphism?

But you do want polymorphism. You asked for it. If you inherit from a polymorphic base class and override one of its virtual functions, you are declaring the intent to use polymorphism. If you didn't want polymorphism, you wouldn't inherit from a polymorphic base class.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

I think you are confused about what a vtable does. A vtable for a class C deriving from B basically maps functions specifiers to function pointers for class C. So if you do

B* ptr = new C;
ptr->foo();

we have to look up at runtime, which function to call. In the end, we need a function pointer to C::foo since B cannot possibly know where that lies, since it does not know about C at all. Hence, here we need C's vtable to make the call. Now you could argue that we do not need Bs vtable here. But ptr could also to an Object of type B, so there you need the B vtable.

Arguably, one could do something like this (of course, pseudo code):

virtual_call_to_foo(B* ptr) {
    if(ptr->is_actually_base_class) {
        ptr->B::foo(); // non-virtual call
    } else {
        ptr->vtable["foo"](); // indirect call
    }
}

But that wouldn't be better than just also using a vtable for B since you already have the indirection there.

Further, note that a call through a pointer to C won't be virtual if C::foo is final:

B* ptr = new C;
ptr->foo();  // virtual call
static_cast<C*>(ptr)->foo(); // non-virtual call, the compiler can inline this
n314159
  • 4,990
  • 1
  • 5
  • 20
  • So an abstract class does not have a vtable? – Henk Jan 24 '21 at 16:13
  • @Henk Yes and no: https://stackoverflow.com/questions/2592438/does-an-abstract-classes-have-a-vtable So sometimes it can be elided if the base call is really purely virtual (only purely virtual functions, no non-static members). But at this point it is also pretty irrelevant, since there is no object of that type that uses the vtable, so its existence are at most some wasted bits in the binary. – n314159 Jan 24 '21 at 16:29
0

When a method is declared, the declaring class decides if it is virtual, according to the nature of what the method does.

When you override such a method, your overriding method is a specialized version of doing the exact same thing. Your overriding method cannot decide that it is doing something that cannot be specialized, the base class has already made that decision. The nature of the method is decided by the class that originally declared it, the base class.

Vtables are an implementation detail that should not affect any of this.

Sean F
  • 4,344
  • 16
  • 30