2

I know that if a class contains any virtual functions, most compilers (if not all) add a vptr pointer to its objects. Some add it as the first element, some as the last. But does the C++ standard mandate usage of vptr and vtable? Could any compiler, theoretically, implement it any other way? If so, what are the guarantees regarding polymorphic objects' storage layout and overall size (e.g. are all the explicitly defined fields (+ padding) in a continuous memory block)?

I don't know if this differs between various C++ standards, that's why I only added the general C++ tag.

NPS
  • 6,003
  • 11
  • 53
  • 90

1 Answers1

2

There's nothing in the C++ standard that mandates a particular implementation of virtual inheritance. The semantics of virtual inheritance are specified in terms of the appropriate syntax, and the expected results. C++ implementations are free to use any technical implementation that produces those results.

For example, let's start with virtual inheritance of entire base classes:

[class.mi]

A base class specifier that contains the keyword virtual specifies a virtual base class. ... For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type.

The standard defines the syntax virtual as introducing virtual inheritance of the base class, and the expected result: that the most derived object contains a single instance of the virtually inherited base class. Full stop. End of story. How a particular implementation goes about doing that, is outside the scope of the standard.

Similarly, for individual virtual functions:

[class.virtual]

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base ... [ a few more requirements ] ... then Derived::vf ... overrides Base::vf.

Some technical requirements omitted. The standard merely specifies that a virtual function in the derived class "overrides" the (same) function in the base class. How a particular C++ implementation goes about doing it, is not specified anywhere.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Correct, but the Q was *not* about virtual inheritance, whose implementation vary a lot. Virtual functions could be in theory implemented in diff ways, but in practice there is uniformity in the general principles: virtual functions are always implemented w/ vptr and vtables. – curiousguy Mar 17 '20 at 03:14
  • Does this mean that one can never depend on the storage layout of objects (or at least the ones with virtual functions)? I mean if something is not in the standard then the program shouldn't rely on it? – NPS Mar 18 '20 at 00:48
  • @NPS Why would even care what the exact layout is? Making sense of stuff like the content of the vtable, for any non trivial hierarchy, is extremely difficult; that's assuming you were fine with throwing away portability. – curiousguy Apr 17 '20 at 22:50
  • @NPS When dealing with almost all types of variables, from builtin types to std classes, you have no specific guarantee about the layout and representation of the object. Originally only unsigned integers provided a strong guarantee (they are binary representation of integers) and signed integers did not. Today 2-compl representation is std, but it wasn't always a portable assumption. And for FP types there is no portable way to decode each bit with bits ops, you have to use std functions. IEEE is quasi std though. – curiousguy Apr 13 '23 at 02:07