C ++: is it a class with a virtual base, but without virtual functions is polymorphic and has VTable?

Consider the following code:

#include <iostream> #include <typeinfo> #include <type_traits> using namespace std; struct A { int data; }; struct B1 : A {}; struct B2 : virtual A {}; struct Base1 : virtual A {}; struct Base2 : virtual A {}; struct Derived : Base1, Base2 {}; int main() { cout << sizeof(B1) << endl; cout << sizeof(B2) << endl; cout << sizeof(Derived) << endl; cout << std::is_polymorphic<B1>::value << endl; cout << std::is_polymorphic<B2>::value << endl; cout << std::is_polymorphic<Derived>::value << endl; return 0; } 

In my system, it prints

 4 8 12 0 0 0 

This means that none of these classes is polymorphic. However, the sizes of B1 and B2 differ exactly in the size of the pointer, which is probably a pointer to a vtable. I executed gcc with -fdump-class-hierarchy and got:

 Vtable for B2 B2::_ZTV2B2: 3u entries 0 4u 4 (int (*)(...))0 8 (int (*)(...))(& _ZTI2B2) VTT for B2 B2::_ZTT2B2: 1u entries 0 ((& B2::_ZTV2B2) + 12u) Class B2 size=8 align=4 base size=4 base align=4 B2 (0x0x3ca5400) 0 nearly-empty vptridx=0u vptr=((& B2::_ZTV2B2) + 12u) A (0x0x3c972d8) 4 virtual vbaseoffset=-12 

The question is: what is a polymorphic class? "Does vtable" mean "be polymorphic and have RTTI" and vice versa? If not, then why would he have at least one virtual function to be polymorphic, if in any case it will have a vtable?

It seems that the definition of a polymorphic class is different from a "class with vtable" because, as we see above, B2 is not polymorphic, but has a vtable and, as I think, should have RTTI. This document clearly states that "polymorphic" - i.e. have at least one virtual function (it is necessary for RTTI to use allowed code on classes.) "

+6
source share
3 answers

Here you do not have enough information: virtual tables are a detail of the implementation. As a result:

  • The standard defines polymorphic classes as classes that can be used in a polymorphic sense: i.e. where behavior can be overridden compilers
  • use virtual tables to implement some functions / behaviors provided by the standard, which include both polymorphic classes and virtual databases.

That way, yes, the compilers I know (MSVC and those that follow Itanium ABI, such as gcc, icc and Clang) will use virtual tables to provide the RTTI needed for dynamic_cast to work in the presence of virtual databases ... and no, it has nothing to do with whether the class is polymorphic or not.

On a tangent, however, Prefers Composition Over Inheritance implies that there is no reason to inherit from a class if there is no behavior that can be undone.

+6
source

Below is a description of std :: is_polymorphic

If T is a polymorphic class (that is, a class that declares or inherits at least one virtual function), provides a constant member value of true. For any other type, the value is false.

Since no functions are defined as virtual, it will return false.

To develop, we must distinguish between polymorphism and vtables. In C ++, vtables are really necessary for polymorphism, but also for other non-polymorphic concepts.

I could try to explain virtual inheritance which when used with multiple inheritance will create a vtable, but this link does it better.

+2
source

For those interested in VTable effects provided by inheritance.

Next example

 struct VB{ // virtual int f(){} }; struct IA:virtual VB{}; int main(int argc, char** argv) { VB* o = new IA; IA* iap = dynamic_cast<IA*>(o); } 

will not compile (g ++ 4.8):

main.cpp: In the function 'int main (int, char **): main.cpp: 26: 34: error: cannot dynamic_cast' o (of type 'struct VB *) for type' struct IA * (source type is not polymorphic) IA * iap = dynamic_cast (o);

While uncommenting the int f() member, gives the desired result.

+1
source

Source: https://habr.com/ru/post/958721/


All Articles