Some questions which have arised and what I think are the answers...
are u sure about this? ... cause i always thought that the pointer created on the object directly points to the v-table of the class
Right, each object points to its own v-table. This is separate from the base class v-table.
that is if i were to write
Base* ptr;
ptr = new Derv();
ptr->pr();
the object created on the free store would have a pointer to Derv's v-table directly .. so why does it have to look at Base's v-table? for the index?
The object created on the free store ONLY has knowledge of itself. It has no idea that the address returned is going to be stored in a Base class pointer. So it would make sense for that (derived) object to have its own v-table.
In your example Dinesh, only the base class has a virtual function and therefore pr only figures in the v-table of base. pr wouldn't figure in the v-table of derv (if it had one) at all since it's not virtual in derv.
Actually, I believe that if a function is declared virtual in a base class, it is implicitly virtual in ALL derived classes as well, whether or not you declare it virtual. So, in Dinesh's example, pr() is virtual in Derv as well.
I dunno if there is a way in c++ to prevent making a function that is already virtual in a base class, virtual in a derived class. Any idea?
Regardless, ALL classes in that hierarchy will have v-tables. One virtual function is ALL you need.
from "Inside the C++ Object Model" by Stanley Lippman ... the constructor of Derv makes the pointer created in the object point to Derv's v-table .. but the index is calculated using knowledge from Base .. cool :):) .. was this what u were trying to say mohnish? .. what i was confused about was to which v-table does the pointer point to ... well thats that :):)
Yes, this is what I was saying. The function addresses in the v-table will appear in the same index, but there will be DIFFERENT v-table for each derived class object. I just didn't phrase it right.
If you have a base class pointer to a derived class object, you will still have a derived class v-table right? So when you call a method on that base class pointer, it will go to the correct index, since they are the same in both the base and derived v-tables, and call the derived class method.
I am still quite confused about the whole thing. If the pointer points to Derv's v-table, how the hell does it even know of the virtual functions in base? That info would only be contained in base's v-table. So how exactly would the index be calculated from base?
Derived classes don't know about base class virtual functions.
Ok consider this...
class Base
{
virtual void fun() { std::cout << "Base"; }
}
class Derived1 : public Base
{
virtual void fun() { std::cout << "Derived1"; }
}
class Derived2 : public Base
{
}
Base class objects have a v-table with one index. That index, say index 0, has the address of Base's fun(). Derived1 also has a v-table with one index. Index 0 has the address of Derived1's fun(). Now, Derived2 does NOT override Base's fun(). But it also has a v-table with one index. That index has the address of Base's fun(). If a derived class choses NOT to override a virtual function, the index in the v-table will point to the address of the base class function.
So when you do...
Base* p;
p = new Derived1;
p->fun() // goes to Derived1's v-table, index 0, which calls Derived1's fun()
p = new Derived2;
p->fun() // goes to Derived2's v-table, index 0, which calls Base's fun()
These indices are calculated by the compiler at compile time and are implementation dependant. I guess the performance penalty is in the indirection. Instead of going straight to the function, you have to go to a table and then from there go to the function.
for(vector< Base* >::iterator g = ptr.begin(); g != ptr.end(); ++g)
(*g)->pr();
This is just a minor thing, but I don't think this is correct...
(*g)->pr()
g is an iterator. An iterator behaves like a pointer. When you dereference an iterator, just like a pointer, you get back an object. So you have to use the dot operator, not the arrow....
(*g).pr();
Like I said, no big deal.
No comments:
Post a Comment