0

Like the title says, e.g. does having 8 derived classes with virtual functions affect performances more than having 2 derived classes? And if so, is the difference negligible?

And what about multiple inheritance (non virtual inheritance)?

Thanks in advance.

Banex
  • 2,890
  • 3
  • 28
  • 38
  • 2
    The only "cost" is the size of the vtable for each object, but in terms of performance it shouldn't make any difference since once the vtable is initialised it's just a simple array lookup. – Jonathan Potter Aug 23 '13 at 00:17
  • I did think that it is usually implemented so there is no penalty for the number of inheritances. – Neil Kirk Aug 23 '13 at 00:36

1 Answers1

2

The common implementation of dynamic dispatch in C++ is by means of a virtual table, which is basically an array of pointers to functions, one for each virtual function in the type. The length of the inheritance chain does not matter, since the vtable holds only one pointer, that of the final overrider for that particular function in the complete object. It will be a single indirection whether the final overrider is in the base or a hundred levels from it.

Multiple inheritance can have a small impact in performance, the amount of which will depend on the actual implementation, but will be independent of the number of bases. In the case of single inheritance the base and the derived object are aligned in memory, that the value of a pointer to the derived type, will have the same address as the same pointer converted to pointer to the base type. In the case of multiple inheritance (assuming that bases are not empty), that is not the case. Only the first base[*] can be aligned with the full object.

The implication of the lack of alignment is that the this pointer will need to be adjusted to point to the appropriate location, depending on which is the final overrider of the virtual function in the complete object. A naïve implementation could store both the offset and the pointer to the function in the vtable, use the offset to adjust the pointer, then jump to the function. This would imply an addition (of possibly 0) to the this pointer for every call to the virtual function. In real life, compilers usually store a single pointer to function that will refer to either the final overrider if the this pointer does not need to be adjusted or to a small trampoline function that will offset the this pointer and forward to that overrider.

You explicitly mentioned that you are not really interested in virtual inheritance, and I will skip the complex further explanations. All of the above is already a bit of a simplification, but hopefully you get the idea. The height of the inheritance chain does not matter, the width can have a very small impact (an extra jump and an addition, or some similar costs, depending on the implementation.

If you are interested, I recommend that you pick up The C++ Object Model by Lippman. Even if the book is over 15 years old, and contains typos and so forth, it describes many of the issues in implementing the object model and comments on some of the solutions.

[*] With the Empty Base Optimization, this becomes all of the empty bases and the first non-empty base.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489