Click to See Complete Forum and Search --> : virtual function
George2
February 10th, 2008, 06:58 AM
Hello everyone,
In the case when function in derived class is virtual, but function in base class is not virtual, when we make base class pointer pointing to derived class' instance, the function in base will be invoked.
I am confused why not the function in Derived class is invoked (this is my question).
When making base pointer pointing to derived class' instance, the layout of derived class should begin with vtable of functions of derived class (virtual function of foo in Derived class in the sample), and the base pointer is pointing to the layout, so when invoking the derived class version function could be found in vtable and it should be invoked. How compiler process this situation internally?
#include <iostream>
using namespace std;
class Base {
public:
void foo()
{
cout << "Base foo " << endl;
}
};
class Derived: public Base {
public:
virtual void foo()
{
cout << "Derived foo " << endl;
}
};
int main()
{
Derived d;
Base* pb = dynamic_cast<Base*>(&d);
pb->foo(); // output Base foo
pb = static_cast<Base*>(&d);
pb->foo(); // output Base foo
pb = &d;
pb->foo(); // output Base foo
return 0;
}
thanks in advance,
George
treuss
February 10th, 2008, 08:07 AM
Base::foo is not virtual, so when calling Base::foo (via a Base *), why should the compiler translate that into a vtable lookup?
TheCPUWizard
February 10th, 2008, 09:22 AM
George, you REALLY need to get some good books, or take a course. You have some major basic gaps in fundamental understanding.
"virtual" comes into existance when it is actually used. It can not be removed at more derived points in the hierarchy. It is implicit and does not need to (but can be) explicitly stated.
"virtual" does not propogate down to base classed. How could it. Virtual functions use the VTable. I compile a class today, no virtual functions. Next week I derive from it into a new project and mark a function as virtual. Do you expect the computer to somehow find all the cd's I burned of the original (no virtuals, hence no vtable) and magically modify them to have a vtable???
George2
February 10th, 2008, 10:26 AM
Thanks treuss and TheCPUWizard,
My question is answered.
George, you REALLY need to get some good books, or take a course. You have some major basic gaps in fundamental understanding.
"virtual" comes into existance when it is actually used. It can not be removed at more derived points in the hierarchy. It is implicit and does not need to (but can be) explicitly stated.
"virtual" does not propogate down to base classed. How could it. Virtual functions use the VTable. I compile a class today, no virtual functions. Next week I derive from it into a new project and mark a function as virtual. Do you expect the computer to somehow find all the cd's I burned of the original (no virtuals, hence no vtable) and magically modify them to have a vtable???
regards,
George
0xC0000005
February 10th, 2008, 10:30 AM
In the case when function in derived class is virtual, but function in base class is not virtual, when we make base class pointer pointing to derived class' instance, the function in base will be invoked.
Its important to note that the address of the derived class and the base class are not different as you seem to think. &d and pb always point to the same physical memory location. Casting (and obviously the direct assignment pb=&d) does not change the address - it only tells the compiler how to deal with the object.
Since in all cases you are telling the compiler to consider the memory address a Base object then it will look in the Base's virtual function table to determine how to deal with virtual functions. Since the Base class does not have a virtual function table entry for foo() then Base::foo() will always be called.
Now if you had made Base::foo() a virtual function, then an entry for for foo() would have been created in Base's virtual function table and when Derived was created it would place its own virtual foo()'s address in the Base's table.
One other thing that I failed to point out above (intentionally, since it would have confused things further) is that in your example Base will not even have a virtual function table since no virtual functions are defined. In other words, the compiler will not even be able to look for foo()'s address in the Base's table since the table doesn't exist - so it MUST call Base::foo().
George2
February 10th, 2008, 10:57 AM
No 0xC0000005,
They are of different address. I posted my code below to verify.
Its important to note that the address of the derived class and the base class are not different as you seem to think. &d and pb always point to the same physical memory location.
#include <iostream>
using namespace std;
class Base {
public:
void foo()
{
cout << "Base foo " << endl;
}
};
class Derived: public Base {
public:
virtual void foo()
{
cout << "Derived foo " << endl;
}
};
int main()
{
Derived d;
Base* pb = dynamic_cast<Base*>(&d);
cout << &d << endl;
cout << pb << endl;
pb->foo(); // output Base foo
pb = static_cast<Base*>(&d);
pb->foo(); // output Base foo
pb = &d;
pb->foo(); // output Base foo
return 0;
}
regards,
George
TheCPUWizard
February 10th, 2008, 12:16 PM
The "Base address" issue can be resolved as follows:
1) Under "Normal" circumstances the address of a base and derived object is the same. There are two common conditions where they will be different
a) Multiple Inheritance. Each of the base addresses MUST be different. The derived class will usually have an address which matches ONE of the base class addresses.
b) The drived class has virtual functions but the base class does NOT. The adresses MAY be different to account for the _vtable (this is implementation specific)
However.
You should (almost) NEVER derive from a class which does NOT have a virtual destructor. Therefore condition "b" above should not occur. You code post violates this.
This information is covered throughly in any decent text book on C++. I suggest "Accelerated C++". Read it from cover to cover, stoping to key in and run via the debugger EVERY sample that is provided. Do NOT move to the next topic until you are confident that you thoughly understand the material.
George2
February 11th, 2008, 12:12 AM
Thanks TheCPUWizard,
My question is answered.
The "Base address" issue can be resolved as follows:
1) Under "Normal" circumstances the address of a base and derived object is the same. There are two common conditions where they will be different
a) Multiple Inheritance. Each of the base addresses MUST be different. The derived class will usually have an address which matches ONE of the base class addresses.
b) The drived class has virtual functions but the base class does NOT. The adresses MAY be different to account for the _vtable (this is implementation specific)
However.
You should (almost) NEVER derive from a class which does NOT have a virtual destructor. Therefore condition "b" above should not occur. You code post violates this.
This information is covered throughly in any decent text book on C++. I suggest "Accelerated C++". Read it from cover to cover, stoping to key in and run via the debugger EVERY sample that is provided. Do NOT move to the next topic until you are confident that you thoughly understand the material.
regards,
George
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.