Mechanism of Vptr and Vtable in C++ - c++

In C++, during dynamic binding, consider the following example...
class Base
{
virtual void fun()
{
cout<<"Base";
}
};
class Derived : public Base
{
void fun()
{
cout<<"Derived";
}
};
int main()
{
Base *bptr;
Derived d;
bptr=&d;
bptr->fun();
}
The output of the above function is "Derived" due to the declaration of virtual keyword/dynamic binding.
As per my understanding, a virtual table (Vtable) would be created which contains the address of the virtual functions. In this case the virtual table created for the derived class points to the inherited virtual fun(). And bptr->fun() will be getting resolved to bptr->vptr->fun();. This points to the inherited base class function itself. I am not completely clear on how the derived class function is called?

Just went through this link virtual table and _vptr
It says that the workflow will be like ..
base_ptr->base_vptr----> to check the access of virtual function in base class.
base_ptr->derived_vptr->virtual_function()---> to call/invoke the virtual function.
Hence the derived class virtual function is called.. Hope you find it helpful.

And bptr->fun() will be getting resolved to bptr->vptr->fun();. This points to the base class function itself.
Wrong. The Derived instance's vptr (a hidden field in each instance) points to the Derived vtable.

The Standard doesn't specify the mechanism by which polymorphism is implemented. All the Standard says is how it should work -- not how compiler vendors should implement it.
That being said, you have it pretty much right as far as GCC under Linux and MSVC under Windows is concerned, and I would expect most other compilers to be similar.

Related

Why does base class pointer to a derived class object with overridden method call a base class method?

#include<iostream>
using namespace std;
class Base
{
public:
void show() { cout<<" In Base \n"; }
};
class Derived: public Base
{
public:
void show() { cout<<"In Derived \n"; }
};
int main(void)
{
Base *bp = new Derived;
bp->show(); // RUN-TIME POLYMORPHISM
return 0;
}
In the above code, show() is declared in the base class and is overriden in the derived class. The base class pointer bp points to a derived class object. Now, when bp to call the non virtual show() function.
Output:
In Base
But, bp points to derived class, so why the base's function is called rather than the derived class function?
// RUN-TIME POLYMORPHISM
In C++ it's opt-in. For a function call to be resolved polymorphically at run-time, the programmer must explicitly say that's desired by marking it virtual.
The reason is that dynamic dispatch is never without a cost, and a staple of C++'s design is that "you don't pay for what you don't need". You must say you really need it for it to be enabled.
You need to make show() virtual to allow kicking in of runtime polymorphism.
virtual void show() { cout<<" In Base \n"; }
The core issue here is that show method is not overridden in the derived class. Starting with C++11 you can use override specifier to ensure that method really does override something so compiler will detect this problem for your:
class Derived: public Base
{
public:
void show() override { cout<<"In Derived \n"; }
};
prog.cc:13:10: error: 'void Derived::show()' marked 'override', but does not override
In order to override a method it should be declared as virtual in base class:
class Base
{
public: virtual
void show() { cout<<" In Base \n"; }
};
Most folks have already answered that you need to declare a function to be virtual for it to bind at runtime when your code executes.
I want to add that without virtual, the method to be called is decided at compile time and it will pick the method of the class whose variable/pointer type you declared. In your case, Base class type.
Additionally, would like to provide a good to read link which can help clear your concept of runtime polymorphism in C++ : https://www.geeksforgeeks.org/virtual-function-cpp/
To complement the other answers posted here, with reference to this comment:
I know, but base pointer point to derived then why call base function?
Please see this post: https://stackoverflow.com/a/50830338/5743288
It follows, therefore, that if you were to do this:
Derived *dp = new Derived;
dp->show();
You would get the following output:
In Derived
even without declaring show() as virtual (because the compiler would then know which method you have said that you want to call).
So, as others point out, if you want the service you have to pay the price (although, even with your original code, the compiler would probably be smart enough to optimise out the virtual function call anyway, see here).
This is actually what is call RUN TIME POLYMORPHISM. And in C++ its programmers discretion to call desired function of base or derived class, based on the object given to base class pointer.
Irrespective of the base class pointer pointing to any derived class object. If the function being called is non-virtual then always base class function will be called to a base class pointer.
To call derived class function from a base class pointer the function must be marked as virtual.
int main(void)
{
Base *bp = new Derived;
bp->show(); // RUN-TIME POLYMORPHISM
return 0;
}
compiler bind it with base class object while compiling
"new Derived" passing object to base but it been binded with base object it refer to same class
once if you add virtual binding will happen run time and once object passed by derived it bind with drived class
In c++,even-though you make the base class pointer point to derived class object, it still calls the function from the base class, this is because of Early binding, so in order to achieve Late binding make the function inside the base class as virtual.
i.e., virtual void show()
{
.......
}
Now, the o/p will be "In Derived".

query on runtime polymorphism in C++

class base
{
public:
virtual void showbase() {
// ----------
}
};
class base1 {
public:
virtual void showbase1() {
// -------
}
};
class derived : public base, public base1
{
void showbase() {
// ----
}
void showbase1() {
// -------
}
};
int main()
{
base* p = new derived();
p->showbase1();
base1* p1 = new derived();
p1->showbase();
}
As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.
To simulate a compiler, consider what a compiler sees:
class base
{
public:
virtual void showbase() {
// ----------
}
};
base* p = /*blah blah*/;
p->showbase1();
Yes, base is a polymorphic class. And p is indeed a pointer-tobase. But since p points just to a base, and importantly not to a base1 (where showbase1 lives) the compiler interprets the above code like this. Obviously, I'm paraphrasing:
Here is a class named `base` with a single virtual method called `showbase`.
Here is a pointer to a `base` object. Call the method named `showbase1`
And the compiler complains:
Um, excuse me buddy, but base doesn't have a method called
showbase1.
You asked:
[My] understanding about virtual function is that compiler deals with
it at run time. Why I am getting compile time error?
Because the code you've written is nonsense. Here basically is how polymorphism works.
You define a base class with virtual methods.
You define a derived class that overrides those virtual methods.
The compiler creates a vtable which maps the names of the methods in the base class to the implementation in the derived class.
When you call a method in the base class through a pointer (or ref) to the base class, the derived class' implementation is called.
But what you are trying to do is:
Define a base class with virtual methods.
Define a derived class which overrides those virtual methods.
Call a function in a completely different class.
As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.
"Deals with it" is pretty vague and vtables are not magic; In C++ virtual dispatch allows for the actual function called to be one that overrides the statically declared virtual function. That means that the function which is being overridden must be known at compile time.
The vtable does not contain information that would be necessary to look up functions at run-time. Instead, it's basically just a list of pointers to overriding functions. The base provides a complete list of its virtual functions and so, given a particular base type, the compiler knows at compile-time where to go in the vtable for that base for a particular function override; The compiler can generate code that goes directly to that spot in the vtable, gets the pointer, and calls the overriding function.
Then, at run-time, when the actual object of derived type is created, the derived object's constructor fills in the base's vtable, so that anything checking the vtable will get pointers to the derived type's functions.
So the problem with your code is that the function you're calling, showbase(), is not on the list of virtual functions for the type the compiler knows you're accessing, base1; The compiler can't know where in base1's vtable to get a pointer for a function override named showbase(), because there is no such entry in base1's vtable.
A base class pointer to a derived class can only access the member functions defined in the base class. It is illegal to try and access other functions defined in the derived class through it. In your case base class does not define showbase1 and therefore this is illegal
base* p = new derived();
p->showbase1(); //illegal
However, you can do this:
p->showbase(); // legal because showbase is a member function of base
Similarly you can't access showbase1 using a base class pointer
base1* p1 = new derived();
p1->showbase(); //illegal
p1->showbase1(); //legal
Your base class(es) only know about their own member functions, so you can't use it this way. You could do this instead:
base* p = new derived();
p->showbase();
base1* p1 = new derived();
p1->showbase1();
To answer your question about runtime polymorphism, it is dealing with runtime polymorphism (late binding) via the vtable, as you say. But with multiple inheritance, there is essentially a vtable for for each base class. You can't access one base class' vtable via a pointer to the other base class.
p'static type s type is base and hence you can only call with it functions that have been definied into base even if at the end, it will be the functions from derived which will be called because p's dynamic type is derived
Same thing happens for p1.
Maybe you meant p->showbase(); and p1->showbase1();

Resolving of vptr

class base {
public:
virtual void fn(){}
};
class der : public base {};
I know that compiler provides a member call VPTR in class which is initialised with the exact VTABLE at run time by constructor. I have 2 questions
1) Which class holds the VPTR. or all the class is having seperate VPTR.
2) When executing statement der d; how VPTR is being resolved at run time?
vtable is created for the class that contains virtual function and for the classes derived from it.It means in your program vtable will be created for base class and der class.Each of these vtables would contain the address of virtual function void fn().Now note that der class doesn't contain the definition of void fn(),hence its vtable contains the address of base class's void fn() function.Thus if u make a call like d.fn(); the void fn() function of base class would get executed.
Note: a virtual table and a virtual pointer are implementation details, though all the C++ compilers I know use them, they are not mandated by the Standard, only the results are.
To answer your specific question: each instance of a class with virtual methods (either its own, or inherited ones) or a class with (somewhere) a virtual inheritance relationship will need at least one virtual-pointer.
There can be several (when virtual inheritance or multi-inheritance are involved).
In your example, a single virtual pointer is sufficient. However it does not make sense to speak of it as being part of a class. The virtual pointer is part of the instance (object), and lives outsides the classes rules because those apply to the language, and the virtual pointer is an implementation mechanism.
1) which class holds the VPTR. or all the class is having seperate VPTR.
Every class object has its own vptr if the class is polymorphic (i.e. contains virtual function or has virtual inheritance.) In this case both the classes has virtual function.
2) when executing statement der d; how VPTR is resolve at run time?
You are just declaring the object of der. But even if you call a function then in this case the call to any function is resolved at compile time. Virtual function resolution comes into picture only when the function is called with pointer/reference.

Which function to call? (delegate to a sister class)

I just read about this in the C++ FAQ Lite
[25.10] What does it mean to "delegate to a sister class" via virtual inheritance?
class Base {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
class Der1 : public virtual Base {
public:
virtual void foo();
};
void Der1::foo()
{ bar(); }
class Der2 : public virtual Base {
public:
virtual void bar();
};
class Join : public Der1, public Der2 {
public:
...
};
int main()
{
Join* p1 = new Join();
Der1* p2 = p1;
Base* p3 = p1;
p1->foo();
p2->foo();
p3->foo();
}
"Believe it or not, when Der1::foo() calls this->bar(), it ends up calling Der2::bar(). Yes, that's right: a class that Der1 knows nothing about will supply the override of a virtual function invoked by Der1::foo(). This "cross delegation" can be a powerful technique for customizing the behavior of polymorphic classes. "
My question is:
What is happening behind the scene.
If I add a Der3 (virtual inherited from Base), what will happen? (I dont have a compiler here, couldn't test it right now.)
What is happening behind the scene.
The simple explanation is that, because inheritance from Base is virtual in both Der1 and Der2, there is a single instance of the object in the most derived object Join. At compile time, and assuming (which is the common case) virtual tables as dispatch mechanism, when compiling Der1::foo it will redirect the call to bar() through the vtable.
Now the question is how the compiler generates vtables for each of the objects, the vtable for Base will contain two null pointers, the vtable for Der1 will contain Der1::foo and a null pointer and the vtable for Der2 will contain a null pointer and Der2::bar [*]
Now, because of virtual inheritance in the previous level, when the compiler processes Join it will create a single Base object, and thus a single vtable for the Base subojbect of Join. It effectively merges the vtables of Der1 and Der2 and produces a vtable that contains pointers to Der1::foo and Der2::bar.
So the code in Der1::foo will dispatch through Join's vtable to the final overrider, which in this case is in a different branch of the virtual inheritance hierarchy.
If you add a Der3 class, and that class defines either of the virtual functions, the compiler will not be able to cleanly merge the three vtables and will complain, with some error relating to the ambiguity of the multiply defined method (none of the overriders can be considered to be the final overrider). If you add the same method to Join, then the ambiguity will no longer be a problem, as the final overrider will be the member function defined in Join, so the compiler is able to generate the virtual table.
[*] Most compilers will not write null pointers here, but rather a pointer to a generic function that will print an error message and terminate the application, allowing for better diagnostics than a plain segmentation fault.
If you add a Der3 what will happen depends on which class it inherits from.
As you know, instantiating a class is only possible when all virtual functions have been defined; otherwise you can only make pointers to them. This is to prevent constructing partially defined objects.
In your example you cannot instantiate Der1 nor Der2 directly because in Der1, bar() is still pure virtual and in Der2, foo() is pure virtual.
Your Join class can be instantiated because it inherits from both and has therefore no pure virtual function.
Once you have made an instance of a class, you can instantiate pointers to non-instantiable classes by dynamic_casting.
From the moment a class has been instantiated, the virtual function mechanism, that works with a table of pointer to functions, will still call the functions that have been defined at instantiation time.
So the key here is that when you create your object, you create an instance of Join. Its virtual functions are defined because you are able to create the object. From that moment, you can call the virtual functions with any pointer to a base class.
I see why this is interesting to explore. In real code this would probably be hardly useful however. As others pointed out, virtual inheritance is more of a fix-this-bad-design-to-work-somehow tool, than a valid desing tool.
Your code produces warnings in VS2010 - the compiler is making you know that dominance is being used. Of course thats not a show stopper, but another discouragement to use this.
If you introduce Der3 like this
class Der3 : public virtual Base {
public:
void bar() {}
};
class Join : public Der1, public Der2, public Der3 {}
the code fails to compile because of ambiguous inheritance of 'void Base::bar(void)'
One point is missing in the discussion ( none-the-less this is quite informative and thanks to all ).
When you 'virtually inherit' a class. What happens is: a pointer to the virtual base class is kept by most of the compilers ( it can be implemented in different ways by different compilers). So if you take the size of Der1 and Der2, it would be atleast 4 bytes on 32 bit and 8 bytes on 64 bit. Because they have a pointer to the virtual base class and therefore, no ambiguity. That is why when you create the object of Join, it first calls the constructor of Virtual Base class ( not really the first call, but it initializes the pointer which came to it through Der1 and Der2 first in its construtor ). In Join compiler can check the pointer name / type and then it makes sure that only one pointer of virtual base class comes to it from Der1 and Der2. You can check even this by sizeof operator. As we know that compiler puts the calls in the constructor silently. Therefore, it first calls the Virtual Base class's constructor in Depth First way. ( can be checked using all the base classes as virtual derivation ). Rest is already explained
This is a pretty stupid example imo and a perfect example of academics making themselves look clever. If this situation ever came up, it would almost CERTAINLY be because of a bug, specifically forgetting to make Der1::foo() virtual.
Edit:
I misread the class definitions. Which is exactly the problem with this type of design. It takes a lot of thought to determine exactly what would happen in each of these cases, which is bad. Making your code readable is by far better than being "clever" like this.

function overriding in c++

could anyone explain function overriding in c++ please! also am confused about virtual function concept. some tutorials say without the keyword virtual, both the derived class and base class objects invoke the base class function. then how does overriding take place?
There's no need to redocument what is already good and out there. I think this and this are a wonderful explanations about virtual functions. Then you probably also need to hear about abstract classes. Let us know if you have further questions.
Read this please. Concentrate on C++ sections. Then ask specific questions you have after reading.
Let me try to post an example (This is out of my head, so there may be slight syntax errors :) )
Baseclass:
class BaseClass
{
public:
void normalFunction();
virtual void virtualFunction();
}
Derived class:
class DerivedClass : public BaseClass
{
public:
void normalFunction();
virtual void virtualFunction();
}
Okay, so we got our classes defined. Now, some examples:
void main()
{
BaseClass base;
DerivedClass derived;
base.normalFunction(); //Invokes BaseClass::normalFunction();
base.virtualFunction(); //Invoked BaseClass::virtualFunction();
derived.normalFunction();//Invokes DerivedClass::normalFunction();
derived.virtualFunction();//Invokes DerivedClass::virtualFunction();
// Okay, nothing special yet, here comes the fun:
BaseClass *basePtr = &base;
BaseClass *derivedPtr = &derived;
basePtr->normalFunction(); //Invokes BaseClass::normalFunction();
basePtr->virtualFunction();//Invokes BaseClass::virtualFunction();
derivedPtr->normalFunction(); //Invokes BaseClass::normalFunction(); !! this is because it's a BaseClass pointer.
derivedPtr->virtualFunction();//Invokes DerivedClass::virtualFunction();
}
.. So, in conclusion, without virtual, the type of the pointer dictates which method will be invoked, with virtual, any type overriding the virtual method will have it's method called regardless of the pointer type :)
This is at a cose of a very minor overhead in the form of a vtable (virtual table), a compiler-detail which will map each method to the different derived types.
Each C++ class that has at least one virtual function contains a "virtual table" or VTABLE which is used to dynamically look up the address of a function at runtime.
Suppose you have two classes: Base and Derived. Further suppose that Derived derives from Base, and that "b" and "d" are instances of Derived, but b's compile-time type is Base and d's is Derived.
Now suppose that both Base and Derived declare a function "foo". Now, if "foo" is declared to be virtual in Base, then "foo" will have an entry in Base's VTABLE, and when you call "b.foo()" or "d.foo()", the compiler will know that it is a virtual function, and it will inject code that will look up the address of "foo" in the VTABLE at runtime.... which will find the address of the definition of "foo" as given in class Derived (i.e. Derived::foo).
Now suppose that both Base and Derived declare a function "foo", but "foo" has not been declared virtual in Base. When you call "b.foo()" or "d."foo()" the compiler will attempt to call Base::foo and Derived::foo directly, bypassing the virtual table lookup. Even though b's runtime type may be Derived, b's compile-time type is Base, and so calling "b.foo()" will result in "Base::foo" rather than "Derived::foo" being called.
In C++, the term "overriding" is used to refer to the former case; that is, when the function is declared as virtual, and another function in a derived class replaces the original function that was defined in the base class. By contrast, the term "overshadowing" is used to refer to the latter case; that is, a function in the derived class is called instead of the one in the base class, simply because it is closer in scope, but it has not truly replaced the function that was defined in the base class.
The override can only be done if you declare the function in the super virtual. Because it is virtual so it's not true ... meaning that is someone invoke it with that signature it may not invoke that function. We have to wait and see at runtime if someone overridden it. That is the meaning of virtual.
class A {
void F_A() { cout << "A' A"; }
virtual void F_B() { cout << "A' B"; }
}
class B : public A {
void F_B() { cout << "B' B"; }
}
A o = new B();
o.F_A(); // Non-virtual so the compiler knows that it can only be the one in class A
o.F_B(); // Virtual so the compiler does not know if at runtime ... o is instance of A or B. So it have to wait and see.
// In this case, it's B at runtime ('`new B()`'), so it run the one in B.
To sum up, if a function (method to be more precise) is declared 'virtual', it can be overridden. Otherwise, it can't be; hence, any invocation always goes to the one in the super class.
Hope this help clarifying.
For Virtual function always remember this thumb rule :
When function is normal then function
of type of object will be invoked,
When function is Virtual then function
of type of actual instance will be
called.
I like to illustrate this example with a Chess board;
class ChessPiece
{
public:
void moveTo(Pos dst);
virtual checkValidAndMoveTo(Pos dst) = 0;
};
class King: public ChessPieve
{ virtual checkValidAndMoveTo(Pos dst);}
class Queen: public ChessPieve
{ virtual checkValidAndMoveTo(Pos dst);}
// etc
ChessPiece* board[8][8];
So when a move is made to square the game will call checkValidAndMoveTo() on the piece.
board[pickedUpPiece.x][pickedUpPiece.y]->checkValidAndMoveTo()
This will now call the appropriate checkValidAndMoveTo() for the particular piece. Once this move is finished we expect it to call MoveTo(). Since at the point it knows what type is is it will drill to down and get the most overidden version of MoveTo() below it current type.