|
-
February 10th, 2008, 07:58 AM
#1
virtual function
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?
Code:
#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
-
February 10th, 2008, 09:07 AM
#2
Re: virtual function
Base::foo is not virtual, so when calling Base::foo (via a Base *), why should the compiler translate that into a vtable lookup?
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf
Premature optimization is the root of all evil --Donald E. Knuth
Please read Information on posting before posting, especially the info on using [code] tags.
-
February 10th, 2008, 10:22 AM
#3
Re: virtual function
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???
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
February 10th, 2008, 11:26 AM
#4
Re: virtual function
Thanks treuss and TheCPUWizard,
My question is answered.
 Originally Posted by TheCPUWizard
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
-
February 10th, 2008, 11:30 AM
#5
Re: virtual function
 Originally Posted by George2
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().
-
February 10th, 2008, 11:57 AM
#6
Re: virtual function
No 0xC0000005,
They are of different address. I posted my code below to verify.
 Originally Posted by 0xC0000005
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.
Code:
#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
-
February 10th, 2008, 01:16 PM
#7
Re: virtual function
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.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
February 11th, 2008, 01:12 AM
#8
Re: virtual function
Thanks TheCPUWizard,
My question is answered.
 Originally Posted by TheCPUWizard
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|