I'm doing a little experiment to try to mimic java's interfaces in C++.
I have a class "Derived" inheriting from base class "Base" and also two interfaces. I notice that with each interface I inherit from, the size of my Derived class goes up, because it has to add more space for each vptr. This seems very expensive to me, so I have two main questions:
- Is there a better way to mimic Java's interfaces in C++?
- Does Java's object size go up with every interface implemented?
Here's the code I'm using:
#include <iostream>
class Base {
public:
int derp;
virtual int getHerp() = 0;
virtual ~Base() { }
};
class Interface1 {
public:
virtual int getFlippy() = 0;
virtual ~Interface1() { }
};
class Interface2 {
public:
virtual int getSpiky() = 0;
virtual ~Interface2() { }
};
class Derived : public Base, public Interface1, public Interface2 {
public:
int herp;
virtual int getHerp() { return herp; }
virtual int getFlippy() { return 6; }
virtual int getSpiky() { return 7; }
};
int main() {
Derived d;
std::cout << sizeof(d) << std::endl;
// prints 40. presumably, Derived/Base vptr + derp + Interface1vptr + Interface2 vptr + herp
}
Yes, the size of the derived type will increase with the number of classes it inherits from.
The exact way it increases and the layout will depend on the ABI for the architecture / environment you're compiling for.
The IA64 ABI is a relatively modern ABI that a number of modern platforms seem to mimic. The documentation for it will give you an idea of how some environments build up a non-POD class type based on various inheritance hierarchies.
To a first order, your guess looks like it's in the ballpark. You need all the vptrs and members you listed. The exact order in which they're placed in the structure matter, along with the alignment constraints among all classes this class inherits from. (Alignment constraints can lead to additional padding.)
So, to your two questions:
I would say "no." The way you're doing it right now is well supported within the language, and all of the pointer rules and polymorphism constructs expect you to do it this way.
Because Java doesn't give you bare pointers, can do other tricks to reduce the total size of an individual object. As @guarav5430 noted, it can avoid increasing the size of individual objects by tracking the set of interfaces a given object implements out-of-band.
So inherent in your question seems to be a concern that these vptrs, etc. will add up to significant storage, which would be a concern if you have a very large number of these objects with such broad interfaces. Depending on what you're doing, certain design patterns such as Flyweight might help.