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.
Related
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.
I have some doubts regarding virtual function or better we can say Run Time Polymorphism. According to me, I assumed the way it works as below,
A Virtual Table (V-Table) will be created for every class that has at least one virtual member function. I believe this is static table and so it is created for every class and not for every object. Please correct me in this if I am wrong here.
This V-Table has the address of the virtual function. If the class has 4 virtual functions, then this table has 4 entries pointing to the corresponding 4 functions.
Compiler will add a virtual pointer (V-Ptr) as a hidden member of the class. This virtual pointer will point to the starting address in the virtual table.
Assume I have program like this,
class Base
{
virtual void F1();
virtual void F2();
virtual void F3();
virtual void F4();
}
class Der1 : public Base //Overrides only first 2 functions of Base class
{
void F1(); //Overrides Base::F1()
void F2(); //Overrides Base::F2()
}
class Der2 : public Base //Overrides remaining functions of Base class
{
void F3(); //Overrides Base::F3()
void F4(); //Overrides Base::F4()
}
int main()
{
Base* p1 = new Der1; //Believe Vtable will populated in compile time itself
Base* p2 = new Der2;
p1->F1(); //how does it call Der1::F1()
p2->F3(); //how does it call Base::F3();
}
If the V-Table gets populated in compile time, why do call it as Run Time Polymorphism ?. Please explain me how many vtables and vptr and how it works using the above example. According to me 3 Vtables will be there for Base, Der1 and Der2 class. In Der1 Vtable,it has address of F1() and F2() of its own, whereas for F3() and F4() the address will point to Base class. Also 3 Vptr will be added as hidden member in Base, Der1 and Der2 class. If everything is decided at compile time, What happens exactly during the run time ?. Please correct me if I am wrong in the concept.
It's obviously implementation defined, but most implementations
are fairly similar, more or less along the lines you describe.
This is correct.
vtables contain more than just pointers to functions.
There's usually an entry pointing to the RTTI information, and
often some information concerning how to fix up the this pointer
when calling the function (although this can also be done using
trampolines). In the case of virtual bases, there could also be
an offset to the virtual base.
This is also correct. Note that during construction and
destruction, the compiler will change the vptr as the dynamic
type of the object changes, and that in the case of multiple
inheritance (with or without virtual bases), there will be more
than one vptr. (The vptr is at a fixed offset with
respect to the base address of the class, and in the case of
multiple inheritance, not all classes can have the same base
address.)
As to your final remarks: the vtables are populated at compile
time, and are static. But the vptr's are set at runtime,
according to the dynamic type, and the function call uses it to
find the vtable and dispatch the call.
In your (very simple) example, there are three vtable, one for
each class. Because only simple inheritance is involved, there
is only one vptr per instance, shared between Base and the
derived class. The vtable for Base will contain four slots,
pointing to Base::f1, Base::f2, Base::f3 and Base::f4.
The vtable for Der1 will also contain four slots, pointing to
Der1::f1, Der1::f2, Base::f3 and Base::f4. The vtable
for Der2 will point to Base::f1, Base::f2, Der2::f3 and
Der2::f4. The constructor for Base will set the vptr to the
table of Base; the constructor for the derived classes will
first call the constructor for the base class, then set the vptr
to the vtable corresponding to its type. (In practice, in such
simple cases, the compiler is probably capable of determining
that the vptr is never used in the constructor to Base, and so
skip setting it. In more complicated cases, where the compiler
cannot see all of the behavior of the base class constructor,
however, this is not the case.)
As to why it is called runtime polymorphism, consider
a function:
void f(Base* p)
{
p->f1();
}
The function actually called will be different, depending on
whether p points to a Der1 or a Der2. In other words, it
will be determined at runtime.
The C++ standard doesn't specify how virtual function calls have to be implemented, but here's a simplified example of the approach that is universally accepted.
From a high-level perspective, the v-tables would look like this:
Base:
Index | Function Address
------|------------------
0 | Base::F1
1 | Base::F2
2 | Base::F3
3 | Base::F4
Der1:
Index | Function Address
------|------------------
0 | Der1::F1
1 | Der1::F2
2 | Base::F3
3 | Base::F4
Der2:
Index | Function Address
------|------------------
0 | Base::F1
1 | Base::F2
2 | Der2::F3
3 | Der2::F4
When you create p1 and p2, they get a pointer that points to Der1's vtable and Der2's vtable, respectively.
The call to p1->F1 basically means "call function 0 on p1's virtual table".
vptr[0] is Der1::F1, so it gets called.
It's called run-time polymorphism because the function that will be called for a specific object is determined at run-time (by making a look-up in the object's vtable).
It's implementation defined. When programming in C++, the only thing that should concern you is that if you declare a method virtual, the run-time contents of the object behind the pointer or reference will decide what code will be called.
Perhaps you should read about that topic first. Here is the C++ specific stuff.
I'm not going to go through four virtual functions and three derived types. Suffice it to say: for the ultimate base class, the vtable has pointers that point to the base class' version of all the virtual functions. For derived classes, the vtable has pointers to all of the derived class's virtual functions; when the derived class overrides a base class function, the function pointer for that function points to the derived class' version of that virtual function; when the derived class inherits a virtual function, the function pointer points to the inherited function.
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.
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.
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.