For example
say X is a class which has a virtual function
and a and b are objects of that class
both a and b will have a vptr installed in them and this vptr will
point to the same vtable
Why not have the vptr as a static data member of the class X so that
every object of that class can use it.
I am sure there is a very good reason for the way it is implemented,
but because of my inexperience with C++ I dont see the reason. Can
anybody please elaborate on the reason.
Thanks,
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Me, too ;-)
> My question is when for every object of a class (which has a virtual
> member) if vptr points to the same vtable, why does every object has
> a copy of the same vptr?
>
> For example
> say X is a class which has a virtual function
> and a and b are objects of that class
> both a and b will have a vptr installed in them and this vptr will
> point to the same vtable
> Why not have the vptr as a static data member of the class X so that
> every object of that class can use it.
Ask yourself this: how will object know which vptr table to take? It
has to know that it's type is X, and hence, when virtual function f is
called on it, it has to do (metacode):
GENERIC_CLASS_STATIC_DATA& sd = this->get_generic__static_data(); ^^^
vptr* p = sd.vptr();
p[index_of_f](this, params);
How do you plan to do ^^^ (should resolve to e.g. X::static_data)?
Solution is exactly that: store some sort of indication of object's
type __in the object__. And that indication is virtual table pointer.
(And when you compile with RTTI on, in the vicinity of said vptr table
you have object's RTTI, too.)
In a way, what you are asking for __is__ what is happening, you are
just looking at things with different eyes. :-)
Goran.
The vtable is interesting only when you have other classes, like Y and
Z, derivning from X. Then a pointer to X could in fact point to an
object of either X, Y, or Z. In that case, the vtable will be used to
select the proper virtual function to call.
If you only have X objects, many compiler will bypass the vtable and
call X functions directly.
Bo Persson
That's not true, objects of the same class can have different vtables. This
happens if they are not exactly of that class but of a derived class.
If you have a debugger that shows the vtable pointer, you could output the
pointer in the base-class constructor and then again in the derived class
constructor for the same object. You would then see that the same pointer
has different values. This also means the value changes during construction
and destruction.
Uli
--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Likely, but quite irrelevant. The C++ standard doesn't say how to
implement dynamic dispatch and polymorphism.
> My question is when for every object of a class (which has a virtual
> member) if vptr points to the same vtable, why does every object has
> a copy of the same vptr?
Because it is one way of how the compiler can deduce the dynamic type of
an object.
> For example
> say X is a class which has a virtual function
> and a and b are objects of that class
> both a and b will have a vptr installed in them and this vptr will
> point to the same vtable
> Why not have the vptr as a static data member of the class X so that
> every object of that class can use it.
Because then polymorphism wouldn't work. If you, at some point, hold a
pointer to a class derived from the class of a or b, then this pointer
may have the same static type, i.e. pointer to the base class. However,
the object it points to is actually of the derived class.
Static members are, however, resolved based on the static type, and thus
you would get the wrong "vtable". Actually, the purpose of the vtable
implmentation strategy is exactly that: Storing some information on the
object in the object without requiring static type information deduced
at compile time - and this is what is required for polymorphism.
So long,
Thomas
Because derived classes will re-use the vptr from their base class to
store a pointer to their own vtable.
>
> For example
> say X is a class which has a virtual function
> and a and b are objects of that class
> both a and b will have a vptr installed in them and this vptr will
> point to the same vtable
> Why not have the vptr as a static data member of the class X so that
> every object of that class can use it.
Suppose there is a second class Y, that is derived from X and c is an
object of class Y.
Now you also have a pointer p (of type X*) that can refer either to b
or to c and you want to call the virtual function through p.
How does the compiler know which vptr/vtable to use? The vptr/vtable
from X is not appropriate if p refers to c, but where the call is
made, the compiler does not even know that Y exists.
That is the reason that each object carries around a vptr. That allows
the compiler to lookup the correct vtable at a call site, without even
knowing about all the possible derived classes.
The whole vtable/vptr mechanism only exists to facilitate indirect
access to virtual members (through a pointer or reference).
With direct access, the compiler has all the information it needs to
determine exactly which function to call, but with indirect access,
there might be as of yet unknown derived classes in play.
Bart v Ingen Schenau
{ quoted clc++m banner removed; please do it yourself. -mod }
I believe the reason why a vptr is stored per object is for caching
reasons. If it is static like you proposed, the CPU would have to
fetch the data from global space and send it to cache. But since we
are accessing the object anyhow, all data (including the vptr) should
be fresh in the cache.
Please correct me if my assumption is wrong.
That's a chicken and egg problem.
How do the objects know what type they are?
It's true that if you write:
X a;
a.SomeVirtualXfunction();
Then the compiler will just call the function bypassing the vtbl
because it KNOWS that a REALLY IS an X but:
void f(X& a)
{
a.SomeVirtualXfunction();
}
Is a realy an X or is it derived?
WHo knows? But its vptr will either point to X::SomeVirtualXfunction()
or Derived::SomeVirtualXfunction().
Regarding the actual, most derived type of a - that is held in the
vtbl too.
If you're realy interested in this stuff I suggest that you get hold
of a copy of "THe annotated C++ reference manual" it's out of date but
it explains all this stuff realy well.
You could do it that way but then every object would have to have a
member that identified its dynamic type so that references and pointers
work correctly. In other words every object must have a way of knowing
its type. In most (probably all) current implementations the vptr does
exactly that.
> My question is when for every object of a class (which has a virtual
> member) if vptr points to the same vtable, why does every object has
> a copy of the same vptr?
>
> For example
> say X is a class which has a virtual function
> and a and b are objects of that class
> both a and b will have a vptr installed in them and this vptr will
> point to the same vtable
> Why not have the vptr as a static data member of the class X so that
> every object of that class can use it.
A static data member exists only once. Not once for each class, but once
for each class tree.
So the static data member of a class Y derived from X and overriding the
virtual function is just the same as the one in X.
It can't have a different value, so the classes can't have different
vtables. This contradicts the initial assumption, which is therefore proven
false.
--
Greetings,
Jens Schmidt
Think again what exactly a vtable is good for. Say X is derived from Y
and you do
Y *c = &b;
c->foo();
where foo is a virtual function actually overridden in X. What would be
called?
Regards, Felix
--
Felix Palmen (Zirias) + [PGP] Felix Palmen <fe...@palmen-it.de>
web: http://palmen-it.de/ | http://palmen-it.de/pub.txt
my open source projects: | Fingerprint: ED9B 62D0 BE39 32F9 2488
http://palmen-it.de/?pg=pro + 5D0C 8177 9D80 5ECF F683
Consider:
#include <iostream>
#include <ostream>
class A {
public:
virtual void f() {
std::cout << "A::f" << std::endl;
}
};
class B : public A {
public:
virtual void f() {
std::cout << "B::f" << std::endl;
}
};
void func(A* a)
{
a->f();
}
int main()
{
A a;
B b;
func(&a);
func(&b);
}
How would the compiler know which "static vtbl" to use in func() when
calling a->f()?
By having each object of a class contain a pointer to it's vtbl (vptr),
then the polymorphism is easily implemented.
DISCLAIMER: Remember that the Standard does not require a vptr or vtbl
(as you noted in your post, it's an implementation detail).
Consider this program, and ask yourself how the print() function
can possibly work with your suggested implementation.
#include <iostream>
class Base {
public:
virtual void foo() = 0;
virtual ~Base() {}
};
class Derived1 : public Base {
public:
virtual void foo() { std::cout << "Derived1" << std::endl; }
};
class Derived2 : public Base {
public:
virtual void foo() { std::cout << "Derived2" << std::endl; }
};
void print(Base const & base)
{
base.foo();
}
int main()
{
Derived1 d1;
Derived2 d2;
print(d1);
print(d2);
}
The problem is, of course, that while print() works on Base objects,
that's the static type of the object, but the dynamic type is really
*either* Derived1 or Derived2, so in the exact same function, print()
needs to invoke 2 different foo() functions, without knowing the type
of the object on which it's calling.
Thus, d1 and d2 have different vtbl pointers, and inside print(),
the "right" function is called by looking at the object's vtbl,
without
caring what type it is. (Furthermore, in the context of print(),
the static type of the object is wrong, as it's an abstract type,
so it would not be possible to access the data the way you suggest.)
--
Chris
What about the X subobject of a class Y that derives from it? The vptr
of those subobjects points to Y's vtable. The entire concept of
dynamic types in a polymorphic hierarchy comes down to "where does the
vptr point?".
Sebastian
It's wrong. Or rather, the issue you mention may be real and a benefit,
but it's not the reason the vptr is stored. As others have said, the
object needs to store /something/ in order to know what class it is, and
it might as well store the vptr which it can use directly.
-- Dave Harris, Nottingham, UK.