Every class which contains one or more virtual function has a Vtable associated with it. A void pointer called vptr points to that vtable. Every object of that class contains that vptr which points to the same Vtable. Then why isn't vptr static ? Instead of associating the vptr with the object, why not associate it with the class ?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Keeping track of variable instances
- Why does const allow implicit conversion of refere
- thread_local variables initialization
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
The runtime class of the object is a property of the object itself. In effect,
vptr
represents the runtime class, and therefore can't bestatic
. What it points to, however, can be shared by all instances of the same runtime class.Your diagram is wrong. There is not a single vtable, there is one vtable for each polymorphic type. The vptr for
A
points to the vtable forA
, the vptr forA1
points to the vtable forA1
etc.Given:
The vtable for
A
contains{ &A::foo, &A::bar }
The vtable for
A1
contains{ &A1::foo, &A::bar }
The vtable for
A2
contains{ &A2::foo, &A::bar }
The vtable for
A3
contains{ &A::foo, &A3::bar, &A3::baz }
So when you call
a.foo()
the compiler follows the object's vptr to find the vtable then calls the first function in the vtable.Suppose a compiler uses your idea, and we write:
The compiler looks in the base class
A
and finds the vptr for the classA
which (according to your idea) is astatic
property of the typeA
not a member of the object that the referencea
is bound to. Does that vptr point to the vtable forA
, orA1
orA2
or something else? If it pointed to the vtable forA1
it would be wrong 50% of the time whena
refers toa2
, and vice versa.Now suppose that we write:
a
andaa
are both references toA
, but they need two different vptrs, one pointing to the vtable forA1
and one pointing to the vtable forA2
. If the vptr is a static member ofA
how can it have two values at once? The only logical, consistent choice is that the static vptr ofA
points to the vtable forA
.But that means the call
a.foo()
callsA::foo()
when it should callA1::foo()
, and the callaa.foo()
also callsA::foo()
when it should callA2::foo()
.Clearly your idea fails to implement the required semantics, proving that a compiler using your idea cannot be a C++ compiler. There is no way for the compiler to get the vtable for
A1
froma
without either knowing what the derived type is (which is impossible in general, the reference-to-base could have been returned from a function defined in a different library and could refer to a derived type that hasn't even been written yet!) or by having the vptr stored directly in the object.The vptr must be different for
a1
anda2
, and must be accessible without knowing the dynamic type when accessing them through a poiner or reference to base, so that when you obtain the vptr through the reference to the base class,a
, it still points to the right vtable, not the base class vtable. The most obvious way to do this is to store the vptr directly in the object. An alternative, more complicated solution would be to keep a map of object addresses to vptrs, e.g. something likestd::map<void*, vtable*>
, and find the vtable fora
by looking up&a
, but this still stores one vptr per object not one per type, and would require a lot more work (and dynamic allocation) to update the map every time polymorphic objects are created and destroyed, and would increase overall memory usage because the map structure would take up space. It's simpler just to embed the vptr in the objects themselves.virtual method table is per class. An object contains a pointer to the run-time type vptr.
I don't think this is a requirement in the standard bust all compiles that I've worked with do it this way.
This is true even in you example.
@Harsh Maurya: Reason might be , Static member variables must be defined before Main function in the program. But if we want _vptr to be static, whose responsibility ( compiler/programmer ) to define the _vptr in the program before main. And how programmer knows the pointer of VTABLE to assign it to _vptr. Thats why compiler took that responsibility to assign the value to pointer(_vptr). This happens in Constructor of class(Hidden functionality). And now if Constructor comes into picture there should be one _vptr for each object.
The whole point of the
vptr
is because you don't know exactly which class an object has at runtime. If you knew that, then the virtual function call would be unnecessary. That is, in fact, what happens when you're not using virtual functions. But with virtual functions, if I haveand a value of type
Parent*
, I don't know at runtime if this is really an object of typeParent
or one of typeSub
. The vptr lets me figure that out.As everyone attest Vptr is a property of an object. Lets see why?
Assume we have three objects
Class Base{ virtual ~Base(); //Class Definition }; Class Derived: public Base{ //Class Definition }; Class Client: public Derived{ //Class Definition };
holding relation Base<---Derived<----Client. Client Class is derived from Derived Class which is in turn derived from Base
Base * Ob = new Base; Derived * Od = new Derived; Client* Oc = new Client;
Whenever Oc is destructed it should destruct base part, derived part and then client part of the data. To aid in this sequence Base destructor should be virtual and object Oc's destructor is pointing to Client's destructor. When object Oc's base destructor is virtual compiler adds code to destructor of object Oc to call derived's destructor and derived destructor to call base's destructor. This chaining sees all the base, derived and client data is destructed when Client object is destroyed.
If that vptr is static then Oc's vtable entry will still be pointing to Base's destructor and only base part of Oc is destroyed. Oc's vptr should always point to most derived object's destructor, which is not possible if vptr is static.