Can we have one vtable shared my multiple classes - c++

Is it possible in C++ to have one vtable shared by multiple classes?
As per my understanding if a class is having a virtual function then it will generate a vtable.So every class should have its own vtable.

Vtables are an implementation detail. C++ doesn't have vtables, it has virtual functions. Vtables just happen to be the most common (if not only) implementation, and the details differ.
What is it that you actually want to achieve?

Polymorphism could be implemented several ways. And vtables could also be implemented several ways. But usually in following case
class A {
virtual foo(){}
}
class B : public A {
virtual foo(){}
}
class C : public B {
void fooNonVirtual(){};
}
classes B and C should have the same vtable.
Example:
A *a = new A;
B *b = new B;
C *c = new C;
a->foo(); // A::foo is called
((A*)b)->foo(); // B::foo is called
((A*)c)->foo(); // B::foo is called
foo for a and b calls different methods because A and B has different vtables. For b and c the same method is called. So compiler could make some optimization and create only one vtable for B and C classes.
fooNonVirtual is not virtual and do not require vtables at all.

You can do
typedef some::Class AnotherClass;
and then these classes would share.
Also, inheritance could - at least theoretically - result in the sharing of vtables.

A vtable is basically a table of virtual functions, so if the two classes have the same virtual functions, it seems pretty straightforward to share the vtable.
struct Class1
{
virtual void func() { /* whatever */ }
};
struct Class2 // can share the vtable with Class1
{
void nonvirtual_func() { /* whatever */ }
};
However, vtable may also contain other info (e.g. the stuff returned by typeid) - in this case, sharing the vtable is impossible. Some compilers have an option to disable RTTI and typeid - so that setting may affect the answer to the question.

It's not really clear what is being asked. A single class may
have many different vtable, depending on how it is used. And
the compiler will merge the vtables of several classes in
a hierarchy. For example:
struct VB { virtual ~VB() = default; };
struct L : virtual VB {};
struct R : virtual VB {};
struct D : L, R {};
In this scenario, the vtable for VB will be different
depending on whether you instantiate an L, and R or a D.
On the other hand, in an object with the most derived type D,
both D and the base class L will probably share the same
vtable.

Related

Itanium C++ ABI primary virtual bases

I was reading here about how primary bases are chosen:
"...2. If C is a dynamic class type:
a. Identify all virtual base classes, direct or indirect, that are primary base classes for some other direct or indirect base class. Call these indirect primary base classes.
b. If C has a dynamic base class, attempt to choose a primary base class B. It is the first (in direct base class order) non-virtual dynamic base class, if one exists. Otherwise, it is a nearly empty virtual base class, the first one in (preorder) inheritance graph order which is not an indirect primary base class if any exist, or just the first one if they are all indirect primaries..."
And after there is this correction:
"Case (2b) above is now considered to be an error in the design. The use of the first indirect primary base class as the derived class' primary base does not save any space in the object, and will cause some duplication of virtual function pointers in the additional copy of the base classes virtual table.
The benefit is that using the derived class virtual pointer as the base class virtual pointer will often save a load, and no adjustment to the this pointer will be required for calls to its virtual functions.
It was thought that 2b would allow the compiler to avoid adjusting this in some cases, but this was incorrect, as the virtual function call algorithm requires that the function be looked up through a pointer to a class that defines the function, not one that just inherits it. Removing that requirement would not be a good idea, as there would then no longer be a way to emit all thunks with the functions they jump to. For instance, consider this example:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
When B and C are declared, A is a primary base in each case, so although vcall offsets are allocated in the A-in-B and A-in-C vtables, no this adjustment is required and no thunk is generated. However, inside D objects, A is no longer a primary base of C, so if we allowed calls to C::f() to use the copy of A's vtable in the C subobject, we would need to adjust this from C* to B::A*, which would require a third-party thunk. Since we require that a call to C::f() first convert to A*, C-in-D's copy of A's vtable is never referenced, so this is not necessary."
Could you please explain with an example what this refers to: "Removing that requirement would not be a good idea, as there would then no longer be a way to emit all thunks with the functions they jump to"?
Also, what are third-party thunks?
I do not understand either what the quoted example tries to show.
A is a nearly empty class, one that contains only a vptr and no visible data members:
struct A { virtual void f(); };
The layout of A is:
A_vtable *vptr
B has a single nearly empty base class used as a "primary":
struct B : virtual public A { int i; };
It means that the layout of B begins with the layout of an A, so that a pointer to a B is a pointer to an A (in assembly language). Layout of B subobject:
B_vtable *A_vptr
int i
A_vptr will point to a B vtable obviously, which is binary compatible with A vtable.
The B_vtable extends the A_vtable, adding all necessary information to navigate to the virtual base class A.
Layout of B complete object:
A base_subobject
int i
And same for C:
C_vtable *A_vptr
int j
Layout of C complete object:
A base_subobject
int j
In D obviously there is only an A subobject, so the layout of a complete object is:
A base_subobject
int i
not(A) not(base_subobject) aka (C::A)_vptr
int j
not(A) is the representation of an A nearly empty base class, that is, a vptr for A, but not a true A subobject: it looks like an A but the visible A is two words above. It's a ghost A!
(C::A)_vptr is the vptr to vtable with layout vtable for C (so also one with layout vtable for A), but for a C subobject where A is not finally a primary base: the C subobject has lost the privilege to host the A base class. So obviously the virtual calls through (C::A)_vptr to virtual functions defined A (there is only one: A::f()) need a this ajustement, with a thunk "C::A::f()" that receives a pointer to not(base_subobject) and adjusts it to the real base_subobject of type A that is the (two words above in the example). (Or if there is an overrider in D, so the D object that is at the exact same address, two words above in the example.)
So given these definitions:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
should the use of a ghost lvalue of a non existant A primary base work?
D d;
C *volatile cp = &d;
A *volatile ghost_ap = reinterpret_cast<A*> (cp);
ghost_ap->f(); // use the vptr of C::A: safe?
(volatile used here to avoid propagation of type knowledge by the compiler)
If for lvalues of C, for a virtual functions that is inherited from A, the call is done via the the C vptr that is also a C::A vptr because A is a "static" primary base of C, then the code should work, because a thunk has been generated that goes from C to D.
In practice it doesn't seem to work with GCC, but if you add an overrider in C:
struct C : virtual public A {
int j;
virtual void f()
{
std::cout << "C:f() \n";
}
};
it works because such concrete function is in the vtable of vtable of C::A.
Even with just a pure virtual overrider:
struct C : virtual public A {
int j;
virtual void f() = 0;
};
and a concrete overrider in D, it also works: the pure virtual override is enough to have the proper entry in the vtable of C::A.
Test code: http://codepad.org/AzmN2Xeh

where is the overridden virtual method saved in the vtable c++ in multiple inheritance

In C++, there is no class representation at run-time but I can always call an overridden virtual method in the derived class. where is that overridden method saved in the vtable? here's a piece of code to demonstrate:
struct B1 {
virtual void f() { ... }
};
struct B2 {
virtual void f() { ... }
virtual void g() { ... }
};
struct D : B1, B2 {
void f() { ... }
virtual void h() { ... }
};
What's the memory layout for an object of class D ? Where are B1::f and B2::f saved in that memory layout (if they're saved at all) ?
An object d of Class D will have only a pointer to the VMT of class D, which will contain a pointer to D::f.
Since B1:f and B2::f can be called only statically from the scope of D class, there is no need for object d to keep a dynamic pointer to those overridden methods.
This of cause is not defined in the standard, this is just the usual/logical implementation of the compiler.
In fact the picture is more complicated, since the VMT of class D incorporates the VMTs of classes B1 and B2. But anyway, there is no need to dynamically call B1::f until an object of class B1 is created.
When compiler uses vtable method of virtual dispatch*, the address of the overriden member function is stored in the vtable of the base class in which the function is defined.
Each class has access to vtables of all of its base classes. These vtables are stored outside of the memory layout for the class itself. Each class with virtual member functions, declared or inherited, has a single pointer to its own vtable. When you call an overriden member function, you supply the name of the base class whose member function you wish to call. The compiler knows about vtables of all classes, to it knows how to locate the vtable of your base class, does the lookup at compile time, and calls the member function directly.
Here is a short example:
struct A {
virtual void foo() { cout << "A"; }
};
struct B : public A { }; // No overrides
struct C : public B {
virtual void foo() { cout << "C"; }
void bar() { B::foo(); }
};
Demo.
In the example above the compiler needs to look up B::foo, which is not defined in class B. The compiler consults its symbol table to find out that B::foo is implemented in A, and generates the call to A::foo inside C::bar.
* vtables is not the only method of implementing virtual dispatch. C++ standard does not require vtables to be used.
Although nothing is mandated in the C++ standard, every known C++ implementation uses the same approach: every class with at least a virtual function has a vptr (pointer to vtable).
You didn't mention virtual inheritance which is a different, more subtle inheritance relation; non-virtual inheritance is a simple exclusive relation between a base class subobject and a derived class. I will assume all inheritance relations are not virtual in this answer.
Here I assume we derive from classes with at least a virtual function.
In case of single inheritance, the vptr from the base class is reused. (Not reusing it just wastes space and run time.) The base class is called "primary base class".
In case of multiple inheritance, the layout of the derived class contains the layout of every base class, just like the layout of a struct in C contains the layout of every member. The layout of D is B1 then B2 (in any order actually, but the source code order is usually kept).
The first class is the primary base class: in D the vptr from B1 points to a complete vtable for D, the vtable with all the virtual functions of D. Each vptr from a non-primary base class points to a secondary vtable of D: a vtable with only the virtual functions from this secondary base class.
The constructor of D must initialize every vptr of the class instance to point to the appropriate vtable of D.

How do you implement polymorphic behaviour with multiple inheritance?

I have never used multiple inheritance but while reading about it recently I started to think about how I could use it practically within my code. When I use polymorphism normally I usually use it by creating new derived instances declared as base class pointers such as
BaseClass* pObject = new DerivedClass();
so that I get the correct polymorphic behaviour when calling virtual functions on the derived class. In this way I can have collections of different polymorphic types that manage themselves with regards to behaviour through their virtual functions.
When considering using multiple inheritance, I was thinking about the same approach but how would I do this if I had the following hierarchy
class A {
virtual void foo() = 0;
};
class B : public A {
virtual void foo() {
// implementation
}
};
class C {
virtual void foo2() = 0;
};
class D : public C {
virtual void foo2() {
// implementation
}
};
class E : public C, public B {
virtual void foo() {
// implementation
}
virtual void foo2() {
// implementation
}
};
with this hierarchy, I could create a new instance of class E as
A* myObject = new E();
or
C* myObject = new E();
or
E* myObject = new E();
but if I declare it as a A* then I will lose the polymorphism of the class C and D inheritance hierarchy. Similarly if I declare it as C* then I lose the class A and B polymorphism. If I declare it as E* then I cannot get the polymorphic behaviour in the way I usually do as the objects are not accessed through base class pointers.
So my question is what is the solution to this? Does C++ provide a mechanism that can get around these problems, or must the pointer types be cast back and forth between the base classes? Surely this is quite cumbersome as I could not directly do the following
A* myA = new E();
C* myC = dynamic_cast<C*>(myA);
because the cast would return a NULL pointer.
With multiple inheritance, you have a single object that you can view any of multiple different ways. Consider, for example:
class door {
virtual void open();
virtual void close();
};
class wood {
virtual void burn();
virtual void warp();
};
class wooden_door : public wood, public door {
void open() { /* ... */ }
void close() { /* ... */ }
void burn() { /* ... */ }
void warp() { /* ... */ }
};
Now, if we create a wooden_door object, we can pass it to a function that expects to work with (a reference or pointer to) a door object, or a function that expects to work with (again, a pointer or reference to) a wood object.
It's certainly true that multiple inheritance will not suddenly give functions that work with doors any new capability to work with wood (or vice versa) -- but we don't really expect that. What we expect is to be able to treat our wooden door as either a door than can open and close, or as a piece of wood that can burn or warp -- and that's exactly what we get.
In this case, classes A and C are interfaces, and E implements two
interfaces. (Typically, you wouldn't have intermediate classes C and
D in such a case.) There are several ways of dealing with this.
The most frequent is probably to define a new interface, which is a sum
of A and C:
class AandC : public A, public C {};
and have E derive from this. You'd then normally manage E through a
AandC*, passing it indifferently to functions taking an A* or a
C*. Functions that need both interfaces in the same object will deal
with AandC*.
If the interfaces A and C are somehow related, say C offers
additional facilities which some A (but not all) might want to
support, then it might make sense for A to have a getB() function,
which returns the C* (or a null pointer, if the object doesn't support
the C interface).
Finally, if you have mixins and multiple interfaces, the cleanest
solution is to maintain two independent hierarchies, one for the
interfaces, and another with the implementation parts:
// Interface...
class AandC : public virtual A, public virtual C {};
class B : public virtual A
{
// implement A...
};
class D : public virtual C
{
// implement C...
};
class E : public AandC, private B, private D
{
// may not need any additional implementation!
};
(I'm tempted to say that from a design point of view, inheritance of
interface should always be virtual, to allow this sort of thing in the
future, even if it isn't needed now. In practice, however, it seems
fairly rare to not be able to predict this sort of use in advance.)
If you want more information about this sort of thing, you might want to
read Barton and Nackman. There book is fairly dated now (it describes
pre C++98), but most of the information is still valid.
This should work
A* myA = new E();
E* myC = dynamic_cast<E*>(myA);
myC->Foo2();
C can't cast to A because it isn't an A; it can only cast down to D or E.
Using A* you can make an E* and through that you can always explicitly say things like C::foo() but yes, there is no way for A to implicitly call functions in C that might have overrides or might not.
In weird cases like this, templates are often a good solution because they can allow classes to act as if they have common inheritance even if they don't. For instance, you might write a template that works with anything that can have foo2() invoked on it.

Multiple inheritance to solve abstract classes

Say I have 4 classes:
class I { public: virtual void X() = 0; };
class A : public virtual I { public: virtual void X() { } };
class B : public I { };
class C : public A, public B { };
I, B and C are abstract, where as A is not. If I simply add virtual to the inheritance of I for B, then A::X() resolves I::X() in C.
However, I cannot change the source of B.
My question: Can I get A::X() to resolve I::X for C without being able to change B? I have tried declaring A and B to be virtual to C to no avail. I am trying to have no redundant code (e.g. have C declare X() { A::X(); }). Any neat hacks?
Also - there are a few questions very much like this, but I couldn't find any talking about using virtual inheritance. Please point to me one if I missed it.
Your problem is with the vtables. In your current code, you have two of them - one in A's I and one in B's I. As long as only A virtually inherits I, you could just as well use regular inheritance and save the overhead. If both virtually inherited I you'd have only one instance of I in C, therefore only one vtable, and A::X could indeed cover the pure virual I::X.
Given you can't change B, the only place you can take care of both vtables is C. In my opinion, the way to go is what you mention - just have C::X forward the call to A::X. There's no code duplication there, and it makes C non-abstract:
class C : public A, public B {
public:
virtual void X() { A::X(); }
};
As for virtual inheritance, there definitively have been some here. But you're welcome to ask...
This is quite good: When virtual inheritance IS a good design?
The problem here is that in C you have two interfaces I. That is why A::x() satisfies
its interface I - but it cannot make not abstract interface I from class B.
For C the only way to have exactly one interface of I - is to change B to derive from I virtually - in this way both I interfaces from A and from B will be merged to one in C. You cannot change B - so the only way is to add this redundant code which you are trying to avoid. I mean define C::X().
The only way I can think of is to compose a B* (or smart variant) into C instead of inheriting from it, and forward the appropriate methods. You can't do it while maintaining the inheritance, because the compiler won't know which I's inheritance chain to follow.

How many vptr will a object of class(uses single/multiple inheritance) have?

How many vptrs are usually needed for a object whose clas( child ) has single inheritance with a base class which multiple inherits base1 and base2. What is the strategy for identifying how many vptrs a object has provided it has couple of single inheritance and multiple inheritance. Though standard doesn't specify about vptrs but I just want to know how an implementation does virtual function implementation.
Why do you care? The simple answer is enough, but I guess you want something more complete.
This is not part of the standard, so any implementation is free to do as they wish, but a general rule of thumb is that in an implementation that uses virtual table pointers, as a zeroth approximation, for the dynamic dispatch you need at most as many pointers to virtual tables as there are classes that add a new virtual method to the hierarchy. (In some cases the virtual table can be extended, and the base and derived types share a single vptr)
// some examples:
struct a { void foo(); }; // no need for virtual table
struct b : a { virtual foo1(); }; // need vtable, and vptr
struct c : b { void bar(); }; // no extra virtual table, 1 vptr (b) suffices
struct d : b { virtual bar(); }; // 1 vtable, d extends b's vtable
struct e : d, b {}; // 2 vptr, 1 for the d and 1 for b
struct f : virtual b {}; // 1 vptr, f reuse b's vptr to locate subobject b
struct g : virtual b {}; // 1 vptr, g reuse b's vptr to locate subobject b
struct h : f, g {}; // 2 vptr, 1 for f, 1 for g
// h can locate subobject b using f's vptr
Basically each subobject of a type that requires its own dynamic dispatch (cannot directly reuse the parents) would need its own virtual table and vptr.
In reality compilers merge different vtables into a single vtable. When d adds a new virtual function over the set of functions in b, the compiler will merge the potential two tables into a single one by appending the new slots to the end of the vtable, so the vtable for d will be a extended version of the vtable for b with extra elements at the end maintaining binary compatibility (i.e. the d vtable can be interpreted as a b vtable to access the methods available in b), and the d object will have a single vptr.
In the case of multiple inheritance things become a bit more complicated as each base needs to have the same layout as a subobject of the complete object than if it was a separate object, so there will be extra vptrs pointing to different regions in the complete object's vtable.
Finally in the case of virtual inheritance things become even more complicated, and there might be multiple vtables for the same complete object with the vptr's being updated as construction/destruction evolves (vptr's are always updated as construction/destruction evolves, but without virtual inheritance the vptr will point to the base's vtables, while in the case of virtual inheritance there will be multiple vtables for the same type)
The fine print
Anything regarding vptr/vtable is not specified, so this is going to be compiler dependent for the fine details, but the simple cases are handled the same by almost every modern compiler (I write "almost" just in case).
You have been warned.
Object layout: non-virtual inheritance
If you inherit from base classes, and they have a vptr, you naturally have as many inherited vptr in your class.
The question is: When will the compiler add a vptr to a class that already has an inherited vptr?
The compiler will try to avoid adding redundant vptr:
struct B {
virtual ~B();
};
struct D : B {
virtual void foo();
};
Here B has a vptr, so D does not get its own vptr, it reuses the existing vptr; the vtable of B is extended with an entry for foo(). The vtable for D is "derived" from the vtable for B, pseudo-code:
struct B_vtable {
typeinfo *info; // for typeid, dynamic_cast
void (*destructor)(B*);
};
struct D_vtable : B_vtable {
void (*foo)(D*);
};
The fine print, again: this is a simplification of a real vtable, to get the idea.
Virtual inheritance
For non virtual single inheritance, there is almost no room for variation between implementations. For virtual inheritance, there are a lot more variations between compilers.
struct B2 : virtual A {
};
There is a conversion from B2* to A*, so a B2 object must provide this functionality:
either with a A* member
either with an int member: offset_of_A_from_B2
either using its vptr, by storing offset_of_A_from_B2 in the vtable
In general, a class will not reuse the vptr of its virtual base class (but it can in a very special case).