Why is a virtual function in a derived class also virtual? - c++

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.

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.

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

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.

Related

Do abstract classes always own a vtable?

I am having problems to understand why abstract classes have vtables. I know that this question has come up under the following posts, which I read so bear with me a moment:
VTABLE for abstract classes C++
Does an abstract classes have a VTABLE?
Why does an abstract class have a vtable?
Here is what I know:
vtables are used to enable polymorphic behavior when I use a derived object via a pointer of the base class. If I now call a virtual method of that base class it will go to the vtable of base look at the real type of the object it is pointing to and look for the closest specialized override of that method and use that one. An class is abstract if it contains at least one pure virtual function, meaning it cannot be instanciated. If it cannot be instanciated I cannot create a base pointer so I can't use it in a polymorphic way? So why would it be able to have a vtable?
If it cannot be instanciated I cannot create a base pointer
This is where your reasoning goes off the rails. Not being able to instantiate does not imply that you cannot create a base pointer. A minimal example:
struct B {
virtual void foo() = 0;
};
struct D : B {
void foo() override {};
};
int main(){
D d;
B* ptr = &d; // base pointer to abstract class
}
So why would it be able to have a vtable?
So that virtual function calls can be dispatched to the implementations in concrete subclasses. On second thought, this is what the vptr is for in general.
The vtable of the abstract base can be used to implement dynamic_cast. It can also be used, in cases where pure virtual functions are called from the constructor or the destructor of the base, as in those cases the vptr won't yet point to the derived vtable.

Polymorphism vs regular inheritance?

I use polymorphism so frequently, but it suddenly dawned upon me. I have the case where my code is:
class A{
class B : public A{
class C : public A{
and I use class A as a polymorphic parameter type for passing in B or C sub types:
//Accepts B and C objects
void aMethod(A* a){
However, I gave A a virtual destructor- this is the only reason A (and B and C) contain a vtable pointer.
So my question is, if I hadn't declared A with a virtual destructor, then A wouldn't be polymorphic- I wouldn't be able to pass objects of type B or C in aMethod()??
So is non-polymorphic inheritance just about sharing code, whereas polymorphism (the base class must have a vtable) allows passing sub types as arguments of the base class type?
In this code you provide,
void aMethod(A a){
the a formal argument is not polymorphic. It's passed by value. When you pass in a B or C object as actual argument, you're just slicing it down to an A, that is, you're copying the A base class sub-object only.
Regarding
” So is non-polymorphic inheritance just about sharing code, whereas polymorphism (the base class must have a vtable) allows passing sub types as arguments of the base class type?
it combines two questions that have to be treated separately.
Inheriting from a non-polymorphic class is about sharing of code, yes, but it also introduces an is-a relationship, which can be important for e.g. passing by reference.
Inheriting from a polymorphic class (one with one or more virtual member functions) allows you to override base class functionality, or to implement it where the base class leaves that as a derived class responsibility – typically by having pure virtual member functions. This means that member functions in the base class can call your derived class’ member functions. Also, that calling member functions via a base class pointer or reference, can call your derived class’s implementations.
Non-polymorphic types also contain a subobject for each base class, and upcasts are still implicit.
You can therefore pass objects of derived classes just fine even when there is no polymorphism. The receiver will act on the base subobject, just as happens for data members and non-virtual functions of polymorphic types.
A class with its destructor the only virtual method, like your class A, is an oddity. AFAIK, such a class has no necessity in well designed code.
From your question, it is not clear whether the virtual destructor is needed (i.e. if you ever call the destructor of classes B or C through a reference or pointer to class A), but if it is, your code smells. If it is not, then simply make the destructor non-virtual.

Confused about non pure virtual classes in C++, what are they for?

I have a class declared as follow:
class TestFoo {
public:
TestFoo();
virtual void virtualFunction();
void nonVirtualFunction();
};
that I try to implement this way
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
which on compilation returns the error:
undefined reference to vtable for TestFoo
I tried :
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
void TestFoo::virtualFunction(){}
which compiles ok which is consistent to the answers to these posts:
Undefined reference to vtable
undefined reference to vtable
What confuses me is that I thought the whole point of declaring a virtual function is that I would not need to define it. In this example, I am not planning to create any instance of TestFoo, but to create instances of (concrete) classes inheriting from TestFoo. But still, I want to define the function nonVirtualFunction for every subclasses of TestFoo.
Something I did not get right ?
Thanks !
the whole point of declaring a virtual function is that I would not
need to define it
Not quite, it says "I may want to replace the implementation of this function by something else in a derived class."
I may have misunderstood your question, but you seem to imply that you don't think you can define pure virtual member function in C++, which you can. You can declare one as follows.
virtual void virtualFunction() = 0;
Normally, a pure virtual function won't be defined, but of course you can. That says "There is no default implementation of this function because it won't always make sense, but I'll provide you with an implementation that you can opt into."
By the way, if a class has any virtual functions, you should also define a virtual destructor, as it is perfectly legal (and often recommended) to have a base class (smart) pointer to a derived class - without a virtual destructor, the object may not be deleted correctly.
... I thought the whole point of declaring a
virtual function is that I would not need to define it ...
For that facility you have a feature called pure virtual methods:
virtual void virtualFunction() = 0; // no linking error now
Note that, a virtual method cannot remain unimplemented. The reason is that for every virtual method declared inside a class body there has to be a vtable entry. Failing to find its body results in linking error.
Purpose of this restriction:
Unless a class is abstract - that is it has at least one virtual function - there is no way you can guarantee to the compiler that you are not going to declare an object of TestFoo. What happens when you do following:
DerivedOfTestFoo obj1;
TestFoo obj2 = obj1, *p = &obj2; // object slicing
p->virtualFunction(); // where is the body?
Other situation; in constructor there is no virtual mechanism:
TestFoo::TestFoo () {
this->virtualFunction(); // where is the body?
}
We can conclude that, compilers follow the rule, "Better to be safe than sorry". :)
Your description matches perfectly with the case of an abstract class. Declare your virtual function as:
virtual void VirtualFunction () = 0;
This means that you are not implementing the function in this class. As a result, the class becomes abstract. That is, no bare objects of this class can be instantiated.
Also, you should provide a virtual destructor.
Update: Some clarifications...
The language allows you to redefine a non-virtual function. Though, the wrong version might be called in some cases:
derived D; // rB is a reference to base class but it
base & rB=D; // points to an object of the derived class
rB.NonVirtualFunction (); // The base-class version is called
For this reason, redefining a non-virtual function is strongly discouraged nowadays. See Scott Meyers' "Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs", item 36: "Never redefine an inherited non-virtual function."
See also item 7: "Declare destructors virtual in polymorphic base classes". An example:
base * pB = new derived;
delete pB; // If base's destructor is not virtual,
// ~derived() will not be called.
In case you wonder why isn't everything virtual by default, the reason is that calling a virtual function is slightly slower than calling a non-virtual one. Oh, and objects of classes with virtual functions occupy a few more bytes each.
If you want make this virtual function as pure virtual function,do not want to define it then, virtual void virtualFunction() = 0;

Virtual Table C++

I read a lot of people writing "a virtual table exists for a class that has a virtual function declared in it".
My question is, does a vtable exists only for a class that has a virtual function or does it also exist for classes derived from that class.
e.g
class Base{
public:
virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
public:
void print(){cout<<"Derived print\n";}
};
//From main.cpp
Base* b = new Derived;
b->print();
Question: Had there been no vtable for class derived then the output would not have been "derived print". So IMO there exists a vtable for any class that has virtual function declared and also in classes inheriting from that class. Is this correct ?
As far as only virtual-function-specific functionality is considered, in a traditional approach to vtable implementation derived class would need a separate version of vtable if and only if that derived class overrides at least one virtual function. In your example, Derived overrides virtual function print. Since Derived has its own version of print, the corresponding entry in Derived vtable is different from that in Base vtable. This would normally necessitate a separate vtable for Derived.
If Derived didn't override anything at all, formally it still would be a separate polymorphic class, but in order to make its virtual functions work properly we could have simply reused Base vtable for Derived as well. So, technically there wouldn't be any need for a separate vtable for Derived.
However, in practical implementations, the data structure that we usually refer to as "vtable", often holds some additional class-specific information as well. That extra information is so class-specific that most of the time it becomes impossible to share vtables between different classes in hierarchy, even if they use the same set of virtual functions. For example, in some implementations the vtable pointer stored in each polymorphic object points to data structure that also stores so called "RTTI information" about the class. For this reason, in most (if not all) practical implementations each polymorphic class gets its own vtable, even if the virtual function pointers stored in those tables happen to be the same.
Yes, your understanding is correct. Any class that has a base with any virtual functions has a vtable.
Yes it's true. Actually, given base's defintion:
class derived:public base{
public:
void print(){cout<<"derived print\n";}
};
is completely equivalent to:
class derived:public base{
public:
virtual void print(){cout<<"derived print\n";}
};
... because you already defined print as virtual in base.
I'd wish the compiler would enforce that...
Yes, that's true. A class inherits all data members from its base class, including the vtable. However, vtable entries are adjusted accordingly (for example if the class overrides a base class virtual method, the corresponding entry in the vtable must point to its own implementation).
But keep in mind that the concept of a 'vtable' is common practice used by vitually every compiler, but it is not compulsory nor standardized.

virtual function - vtable

Let's say I have class A who inherits from class B and C (multiple inheritance).
How many vtable members class A would have ?
What's the case in single inheritance ?
In addition, suppose:
Class A : Public B {}
and:
B* test = new A();
Where does test gets its vtable from? What's assignment?
I assume it gets B's part of A's vtable, but does A's constructor changes its fathers (B) vtable too ?
First, vtable's are implementation specific. In fact, nowhere in the standard is specified that vtable's must exist at all.
Anyway, in most usual cases, you would get one vtable pointer per base class with virtual functions. And, as Yuval explained, nobody "fills" the vtable's when an object is constructed; you have one vtable per class with virtual functions, and objects just have pointers to their correct vtable (or vtable's, in case of multiple inheritance). In your single-inheritance example, test would have a pointer to A's vtable, assuming that A has at least one virtual function (inherited from B or newly declared in A).
Generally speaking - you need at least one vtable entry for each virtual function you inherit. If you have no virtual functions, you have no vtable.
Generally speaking, a subclass will have a vtable pointer to each of the multiple superclasses it inherits from (assuming, obviously, that each of those classes have at least one virtual function).
I'm not quite sure I understood your second question. When building an object, part of the construction process is setting the relevant vtable pointers, this is something that is done implicitly by the c++ compiler by static analysis of the inheritance hierarchy. None of the vtables change, they are merely pointed at.
When a class defines virtual functions, the compiler silently inserts a hidden vPtr data member for each supported interface.
The vPtr points to the correct vTable for the object.
The vTable contains a list of addresses which point to function implementations.
Here's an example of sorts.
class Foo: public Bar, public Baz
{
VTable* bar_vPtr;
VTable* baz_vPtr;
// Bar overrides/implementations
void barOverride();
// Baz overrides/implementations
void bazOverride();
};
VTable:
&barOverride() // address of implementation
VTable:
&bazOverride() // address of implementation
When an object is created, the memory is created for the data members and not the methods. The methods will be in a common location to be accessible by all the objects. This [ one per class ] applies to VTable as it merely consists of a function pointer for each virtual function in the class.
As mentioned by Steven, compiler adds a hidden pointer to the base class, which is set when a class instance is created such that it points to the virtual table for that class, This pointer is also inherited by derived classes.
When an object of the derived class is assigned to the base class pointer, the hidden pointer in the base class is replaced with the address of the derived class's vtable.