Reputation: 5807
there is something i still don't get.
for every class i declare there is a hidden vptr member pointing to the class virtual table.
let's say i have this declaration :
class BASE
{
virtual_table* vptr; //that's hidden of course , just stating the obvious
virtual void foo();
}
class DERIVED : public BASE
{
virtual_table* vptr; //that's hidden of course also
virtual void foo();
virtual void cho();
}
first i want to understand something, is it really the same member name for the vptr both for the derived and the base ?
second, what happens in this situation :
base* basic = new derived();
i get it, the basic variable gets derived's vptr, but how is that happening ? cause usually when conversion taking place , derived's base part (including base's vptr) should be assigned to basic, and not derived's vptr. maybe it's different if there is a variable with the same name in both classes, i dunno.
third and last question : when i have
base* basic = new derived();
is there a way to call with basic - base's member function even though it's virtual ?
thanks
Upvotes: 3
Views: 7764
Reputation: 11028
First of all, virtual tables are not part of the C++ standard. A C++ compiler is free to implement virtual functions any way they feel appropriate. Usually they will use virtual tables, true; but in this case they can implement them any way they feel appropriate.
In most usual implementations, basic
does not get derived
's vptr
; *basic
's vptr
will point to derived
's vtable
, which is not really the same. basic
is just a pointer, and it is the object pointed that has a vptr
. No conversion involved. In any case, vptr
is just an internal name for an implementation detail. There is no real class member called vptr
.
And you can always call any base-class function just by qualifying it with the class name (in your case, basic->BASE::foo()
).
UPDATE: Just for the record, I have tried creating a class in VC++2008 with a pointer called __vfptr
(that is the internal name for the vptr in this compiler), and it works as expected, even though the debugger gets a bit confused by the variable name.
Upvotes: 3
Reputation: 37427
first, yes, it is the same member. It is automaticaly assigned a first time when running base constructor, and assigned a second time when running the derived constructor. (In the case of default empty constructors, the useless assignements of base is optimized away.)
second, there is no real conversion. In fact, the derivation can be named a "is a" relationship. In this case, derived "is a" base. If you consider the first bytes of memory of a derived object, they have the same meaning than the first bytes of a base object.
third, you can call basic member function as follows: basic->base::foo();
Upvotes: 3
Reputation: 8529
3). Ya u can .base* basic = new derived();
basic->BASE::foo(); // will call base class method and resolved at compile time.
2). It is possible when there is not virtual stuff in class(if derived class does not override any base class functions), but if derived class has virtual functions (overrided )so to achieve run time polymorphism its necessary for compiler to initialize vptr of base by vptr of derived and it augments that code.
1).Yes the interface function prototype has to be same else base class function get hidden by derived class function (e.g. if parameter defers in derived class function ) .
Upvotes: 1
Reputation: 208323
On the second question. (And this is not stated in the standard, and can be implemented in other ways, so just take the general ideas out of it. It is also oversimplified for single inheritance hierarchies, multiple inheritance makes everything more complex).
The memory layout of a derived and a base object coincides 100% in as much as the size of the base object (including any data injected by the compiler). This means that a pointer that has base
type and actually points to derived
will actually point to a piece of memory that can be interpreted as a base
object, the layout is the same even if the contents (vptr value) are different.
base derived
base_vptr base_vptr
base_attrs base_attrs
derived_vptr
derived_attrs
When you create an instance of derived
the compiler will call the appropriate derived
constructor, whose initialization list starts by calling the base
constructor. At this point the vtable pointer base_vptr
is set to point to the virtual table of the base class, and as such all pointers there refer to base::method
. After the base
constructor has completed, the base_vptr
is updated in derived and it is set to point to the derived
vtable, so instances there point to derived::method
if the method is overriden in derived
. At this point derived_vptr
points to the derived vtable for virtual methods added in derived
and would point to derived::new_method
...
Just to make a point: the vtable does not necessarily store pointers into the actual methods. In some cases, intermediate code must be executed whenever a virtual method is called, and that happens whenever multiple inheritance comes into play. Things get more complicated, as the derived class can only be aligned with one of its bases (usually the first one declared). This is where things really get tricky. Upcasting to base2
modifies the pointer so that it points to the memory location that can be directly be interpreted as a base2
instance, so the contents of a pointer (memory location) of type base2
pointing to an object of type derived
will not coincide with a pointer of type derived
into the same object. At this point, if a virtual method from base2
is called, the system must perform some magic to recalculate the correct position of the implicit this
argument that is handed into the derived::method_from2
virtual method (that must point back to the whole derived
object and not just the base2
subobject.
Upvotes: 1
Reputation: 52519
The vtable
(virtual_table
, in your words) will point to different addresses for BASE
and DERVIVED
provided DERIVED
overrides at least one virtual function from BASE
. Each instance of BASE
will have the same vtable
pointer however (ditto for DERIVED
).
When you do something like:
someobject->foo();
this is translated to:
someobject->vtable[COMPILER_GENERATED_OFFET_FOR_FOO]();
The vtable
is an array of function pointers where the offset to some virtual function (say foo
) is the same for all classes in the class hierarchy.
Upvotes: 1
Reputation: 37188
You can check vtable implementation details here; this is what the GNU compilers, and AFAIK some other mainly Unix compilers use. Especially the "Vtable layout" examples page is instructive.
As others have noted, this is an implementation detail, the C++ standard itself is silent on the matter.
Upvotes: 0
Reputation: 50097
first: yes: each instance will get that member variable declared by the base.
second: in that situation you'll be able to access only members of the base class.
third: you can call it if it is virtual, as long as it's not pure virtual (which means it doesn't have any implementation and it's declared like this: virtual void foo() = 0;
).
Upvotes: 0
Reputation: 9891
Calling the parent method from a derived child: old question
Upvotes: 0