Base having a virtual function and Derived also having one virtual function like this,
class Base
{
private:
int i;
public:
Base(int data = 9):i(data)
{
cout << "In Base class constructor" << endl;
}
void display()
{
cout << "In Base class" << endl;
cout << "i = " << i << endl;
}
virtual ~Base()
{
cout << "In Base class destructor" << endl;
}
};
class Derived: public Base
{
private:
int j;
public:
Derived(int data = 10):Base(11),j(data)
{
cout << "In Derived class constructor" << endl;
}
virtual void display()
{
cout << "In Derived class" << endl;
cout << "j = " << j << endl;
}
~Derived()
{
cout << "In Derived class destructor" << endl;
}
};
Now in gdb I see the total size of the Derived class object is 16 bytes (int+int+_vptr+_vptr), but when I print each object in gdb I'm getting confused, for base class it's showing like this
$1 = {_vptr.Base = 0x401010, i = 11} and it's fine, but for derived it's showing something like this
$2 = {<Base> = {_vptr.Base = 0x401010, i = 11}, j = 10}
I'm not seeing the virtual pointer of the derived class. As per my understanding in addition to the base class virtual pointer which is inherited, there should be one more virtual pointer in the derived class that should point to it's own virtual table. Am I doing something wrong here or is there any other way to get it?
The derived class has its own vtable. So objects of that type have a single pointer to it. That vtable contains entries that point to Bases member functions if they aren't overridden. So there is no need for a pointer to Bases vtable in objects of type Derived.
The reason _vptr.Base appears in Derived is because you didn't override any functions. The compiler doesn't generate a vtable for Drived because it will just be a duplicate of Bases.
With single inheritance, there is typically just one virtual function pointer: it points to something like an array of function pointers. The number of entries contributed by the base class is known and the derived class just tags its own virtual functions to the end.
Of course, how the virtual function table actually works exactly depends on the respective ABI. You can have have a look, e.g., at the Itanium C++ ABI which is used on Linuxes and possibly on other systems.
The derived class doesn't have a separate, additional pointer to its vtable - rather, the vtable pointer inherited from the base class will be overwritten to point to the derived class's vtable as the derived class's constructor runs (and later reverted as the destructor runs).
That way, when operations are done on a Base* or Base& to the Base member embedded in a constructed derived object, the pointer to the VDT seen (at the usual offset into the Base object) allows dispatched to the derived class's methods.
Related
So I have these classes:
class Base {
public:
Base() {cout << "made a base" << endl;}
virtual void getType() const { cout << "Im a base" << endl;
virtual ~Base() {}
//other members...
}
class Derived: public Base {
public:
Derived() {cout << "made a derived" << endl;
virtual void getType() const { cout << "Im a derived" << endl; }
virtual ~Derived() {}
//other memebrs...
}
int main() {
Base* test = new Derived();
test->getType();
return 0;
}
output:
made a base
made a derived
Im a derived
Now I know that the output is Im a derived because of polymorphism, however I would like to know how this works internally with Vftables, how can It call the correct function, the vtable inside test points to the Base class getType() function because of the type of test so how can it know that it is Derived::getType() and not Base::getType().in other words what does my program do at runtime when it see's this declaration test->getType()?
Thanks in advance.
When you do Base* test = new Derived():
The V-Table pointer of object test is set to point to the V-Table of class Derived.
Note that when the object is created - via new Derived() - you are explicitly calling a function (the constructor) of class Derived and not of class Base.
And when this function is called, it sets the v-table pointer of the new object to point to the V-Table of class Derived and not of class Base.
AFAIK, the actual V-Tables (of both classes), are generated by the linker past compilation.
Supplemental:
The program doesn't need to "know" that a function is virtual.
In case of a non-virtual function call, the compiler adds a JUMP instruction to a constant address (i.e., the address of the non-virtual function, which is resolvable during compilation).
In case of a virtual function call, the compiler adds a JUMP instruction to an address stored in (pointed by) a variable, whose value is resolved only during runtime.
#include<iostream>
using namespace std;
class A
{
public:
A() { cout << "A Creator" << endl; }
~A() { cout << "A Destroyer" << endl; }
};
class B : public A
{
public:
B() { cout << "B Creator" << endl; }
virtual ~B() { cout << "B Destroyer" << endl; }
};
void main()
{
A* temp = new B;
delete temp;
}
I'm not sure I think this is what I think.
I am definitely wondering why the error is happening.
temp allocates a derived class B and stores it in a pointer type (base class A).
At this time, the compiler is based on the pointer data type.
The virtual function table is not created because the base class destructor does not have a virtual declaration.
Class B creates a virtual function table. A virtual function table pointer is also created.
When trying to destroy temp, temp calls the pointer data type destructor and issues a problem.
Class B virtual function table pointer can not be found.
This is because the pointer data type is a non-virtual base class.
Your code invokes undefined behavior.
Excerpt from the "Effective C++" book by Scott Meyers explains why:
When derived class object is deleted through a pointer to a base class
with a non-virtual destructor, results are undefined.
Your base class A should have a virtual destructor:
virtual ~A() { std::cout << "A Destroyer" << '\n'; }
If classes are meant to be used in polymorphic ways then the base class should have the virtual destructor.
delete on a pointer whose pointed type does not have a virtual destructor has undefined behviour if the pointer points to a base sub-object. temp points to the base sub-obect of a B instance and A::~A is non-virtual.
To fix, declare A::~A virtual.
I create a object of derived class and a base class point for it ,
and then I use the dynamic_cast convert base class point to derived class point .
I delete the derived class point , but the program calls the derived destructor and the base destructor. Why does the program call the base destructor? After all, the base destructor isn't a virtual function....
#include<iostream>
#include<stdlib.h>
using namespace std;
class con {
private:
double num;
public:
con() {
num = 0;
cout << "default..." << endl;
}
void getnum() {
cout << num << endl;
}
};
class base {
public:
virtual void A() {
cout << "it is base A" << endl;
}
void B() {
cout << "it is base B" << endl;
}
~base() {
cout << "it is base decon" << endl;
}
};
class child : public base {
public:
void A() {
cout << "it is child A" << endl;
}
void B() {
cout << "it is child B" << endl;
}
~child() {
cout << "it is child decon" << endl;
}
};
int main(int argc, char** argv) {
base* b = new child();
child* c = dynamic_cast<child*>(b);
delete c; //the program print "it is child decon" "it is base decon"
getchar();
return 0;
}
Case 1: If you delete a pointer derived class, it always calls the destructor of the derived class first, then the destructor of the base class.
Case 2: If you delete a pointer to the base class of a derived class with a non-virtual base class destructor, it doesn't know about the derived class so it just deletes the base class.
Case 3: If you delete a pointer to the base class of a derived class with a virtual base class destructor, it uses virtual dispatch to the destructor of the derived class, then calls the destructor of the base class.
Case 2 is bad. It can cause resource leaks, etc. It should be avoided by always declaring destructors virtual in classes that are intended to be base classes.
Your example illustrates case 1.
If you want to see case 2 in action try delete b rather than delete c in your example.
Destructors in C++ don't "overload" as such; they chain up. When you say
{
child c;
}
then at the closing brace the compiler will insert a call to ~child(), which will in turn call ~base() (and the destructors of other base classes, if you had them). This is essential to avoid memory leaks -- otherwise how would base's members be destroyed? Note that this doesn't require the base destructor to be virtual.
This works the same way when you manually destroy something with delete:
child* c = new child{};
delete c; // runs ~child(), which calls ~base()
again, this doesn't require the destructor to be virtual.
What a virtual destructor does do is allow you to destroy a variable with dynamic type child using a pointer to a base, i.e.
child* c = new child{}
base* b = c;
delete b; // Will call ~child() if destructor is virtual, otherwise ~base()
I was going through notes about virtual destructors and virtual functions. Now, when I tried to write a simple code to validate my learning,
#include <iostream>
using namespace std;
class Base{
public:
Base (){
cout << "Constructing base" <<endl;
}
void doSomething (){
cout << "inside void " << endl;
}
~Base (){
cout << "Destructing base" << endl;
}
};
class Derived : public Base{
public:
Derived(){
cout << "Constructing derived" << endl;
}
void doSomething (){
cout << "inside derived void " << endl;
}
~Derived(){
cout << "Destructing derived" << endl;
}
};
int main(){
Derived *d = new Derived();
d->doSomething();
delete d;
}
Shouldn't I expect an output like so:
Constructing base
Constructing derived
inside void
Destructing base
because I didn't use the virtual keyword for the destructors of both derived and base? Can you please explain virtual functions and virtual destructors in view of this sample?
I get this output:
Constructing base
Constructing derived
inside derived void
Destructing derived
Destructing base
I'm confused.
I use g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 in Ubuntu 12.04.
You are getting the correct output.
Derived *d = new Derived();
d->doSomething();
It's calling the Derived class member function. For the runtime function call dispatch mechanism to work, you need to qualify the member functions with virtual keyword. Also you should write -
Base *d = new Derived();
In the above case, static type of d is different from the dynamic type. So, derived class member function will be called at runtime. Also, Base class destructor should be virtual in such scenario.
Hey, so if I have a Base class and 2 derived classes...
class Base
{
virtual void Output()
{
cout << "OUTPUTTING A BASE OBJECT" << endl;
}
};
class Derived : public Base
{
void Ouput()
{
cout << "OUTPUTTING A DERIVED" << endl;
}
};
class OtherDerived : public Base
{
};
As I understand it, if I try to call Output from OtherDerived, it would fail. Is there a way to override Output for some derived versions of Base but not others?
Calling Output for objects of the OtherDerived class fails not because it's virtual, but because it's declared private in Base (well not explicitly - but private is the default in classes when nothing else is specified)
Change the declaration of Base to:
class Base
{
public:
virtual void Output()
{
cout << "OUTPUTTING A BASE OBJECT" << endl;
}
};
And this will work. protected will also work. Since Output isn't pure virtual, it can be called from subclasses that don't override it.
It would not fail - it would call Base::Output. What you want, ie. overriding "for some derived classes, but not others" is how inheritance works. You don't need to do anything further.