Update: Replaced the destructor example with a straight up method call example.
Hi,
If I have the following code:
class a
{
public:
virtual void func0(); // a has a VTable now
void func1();
};
class b : public a
{
public:
void func0() { a::func0(); }
void func2();
};
- Is there a VTable in B? B has no virtual functions but calls a::func0() from b::func0()
- Does func1 reside in a VTable? It's not virtual.
- Does func2 reside in a VTable?
- Will the answers to the above be different if there wasn't a a::func0() call in b::func0()?
Thanks
If you declare virtual functions you should also declare your destructor virtual ;-).
B has a virtual table, because it has a virtual function, namely
func0()
. If you declare a function (including a destructor) virtual in a base class, all its derived classes will have the function with same signature virtual as well. And it will cause them to have a vtable. Moreover, B would have the vtable even if you didn't declarefunc0
in it explicitly.Non-virtual functions are not referenced through vtables.
See 2.
No. Classes' vtables are constructed based on class declarations. The bodies of class' functions (let alone other functions) are not taken into account. Therefore, B has a vtable, because its function
func0()
is virtual.
There also is a tricky detail, although it's not the gist of your question. You declared your function B::func0()
as inline. In gcc
compiler, if a virtual function is declared inline, it retains its slot in virtual table, the slot pointing to a special function emitted for that inline one (that counts as taking its address, which makes the inline emitted). That means, whether the funciton is inline doesn't influence amount of slots in vtable and its necessity for a class.
Yes, because its base class has one; also its destructor is virtual (even though you didn't declare it virtual) because the destructor of the base class is virtual.
No
No.
No. Actually I don't think the current code is legal: the compiler will invoke the A destructor after it invokes the B destructor even if you don't explicitly call ~A from ~B; so I don't think you should invoke ~A from ~B even if the compiler allows you to.
Referring to the updated example:
- Yes, b has a vtable. Note that b::func0() is virtual (overrides a::func0()), even though you didn't explicitly label it as virtual. Weird C++ "loophole", I guess.
- No. Non-virtual functions do not reside in the vtable.
- See 2.
- No. You've overridden a:func0(); it doesn't matter if you call a::func0() or not.
A few additional notes (compiler dependent, but these are pretty common generalizations):
- Every instance of b will have a pointer to a vtable, because you're derived from a class that has virtual functions.
- This would be the case even if you didn't define b::func0().
- In this situation, the compiler might have instances of b point to a's static vtable, or it might create a static vtable for b and fill it with pointers to pointers to members of a.
- But it's still required, so that you can properly access an instance of b via a pointer to a.
- If base class function is virtual then if you override that function in derived class it is implicitly virtual even if you don't specify explicitly. If class has a virtual function then it has a v table.
- Only virtual functions present in vtable, function1 will not reside in vtable
- function2 will not reside in vtable same reason above
- Creation of vtable does not depend on whether you call that function from base class or from somewhere else. Function call does not decide creation of vtable.
Update: Replaced the destructor example with a straight up method call example.
Hi,
If I have the following code:
class a
{
public:
virtual void func0(); // a has a VTable now
void func1();
};
class b : public a
{
public:
void func0() { a::func0(); }
void func2();
};
- Is there a VTable in B? B has no virtual functions but calls a::func0() from b::func0()
- Does func1 reside in a VTable? It's not virtual.
- Does func2 reside in a VTable?
- Will the answers to the above be different if there wasn't a a::func0() call in b::func0()?
Thanks
If you declare virtual functions you should also declare your destructor virtual ;-).
B has a virtual table, because it has a virtual function, namely
func0()
. If you declare a function (including a destructor) virtual in a base class, all its derived classes will have the function with same signature virtual as well. And it will cause them to have a vtable. Moreover, B would have the vtable even if you didn't declarefunc0
in it explicitly.Non-virtual functions are not referenced through vtables.
See 2.
No. Classes' vtables are constructed based on class declarations. The bodies of class' functions (let alone other functions) are not taken into account. Therefore, B has a vtable, because its function
func0()
is virtual.
There also is a tricky detail, although it's not the gist of your question. You declared your function B::func0()
as inline. In gcc
compiler, if a virtual function is declared inline, it retains its slot in virtual table, the slot pointing to a special function emitted for that inline one (that counts as taking its address, which makes the inline emitted). That means, whether the funciton is inline doesn't influence amount of slots in vtable and its necessity for a class.
Yes, because its base class has one; also its destructor is virtual (even though you didn't declare it virtual) because the destructor of the base class is virtual.
No
No.
No. Actually I don't think the current code is legal: the compiler will invoke the A destructor after it invokes the B destructor even if you don't explicitly call ~A from ~B; so I don't think you should invoke ~A from ~B even if the compiler allows you to.
Referring to the updated example:
- Yes, b has a vtable. Note that b::func0() is virtual (overrides a::func0()), even though you didn't explicitly label it as virtual. Weird C++ "loophole", I guess.
- No. Non-virtual functions do not reside in the vtable.
- See 2.
- No. You've overridden a:func0(); it doesn't matter if you call a::func0() or not.
A few additional notes (compiler dependent, but these are pretty common generalizations):
- Every instance of b will have a pointer to a vtable, because you're derived from a class that has virtual functions.
- This would be the case even if you didn't define b::func0().
- In this situation, the compiler might have instances of b point to a's static vtable, or it might create a static vtable for b and fill it with pointers to pointers to members of a.
- But it's still required, so that you can properly access an instance of b via a pointer to a.
- If base class function is virtual then if you override that function in derived class it is implicitly virtual even if you don't specify explicitly. If class has a virtual function then it has a v table.
- Only virtual functions present in vtable, function1 will not reside in vtable
- function2 will not reside in vtable same reason above
- Creation of vtable does not depend on whether you call that function from base class or from somewhere else. Function call does not decide creation of vtable.
0 commentaires:
Enregistrer un commentaire