Can a derived class be smaller than its parent class? - c++

I'm asking this about C++ since I'm familiar with that but the question really explains itself: is there a language in which we can derive a class and make it occupy less space in memory than the original class?
This question is more of a gimmick than an actual problem I'm trying to solve, but I could imagine that some really high-performant code could benefit from this kind of memory optimization:
Suppose we have:
class Person {
std::string name;
unsigned int age;
}
class PersonNamedJared {
}
In theory, we don't need a field "name" in this subclass since it'll always be "Jared", which could allow for better memory efficiency.
Is the only way to make this happen by replacing the 'name' field in Person with a get_name() function that we simply override in PersonNamedJared to always return "Jared"? How would we still make the name variable in the base class?
I know this example is really bad practice, but it's the best I could come up with. I think there are legitimate reasons to implement this kind of pattern.

Can a derived class be smaller than its parent class?
No. A derived class always contains a base class sub object. An object can never be smaller than its sub objects, so a derived class can never be smaller than its base.
Is the only way to make this happen by replacing the 'name' field in Person with a get_name() function that we simply override in PersonNamedJared to always return "Jared"?
That would be one way to achieve it.
How would we still make the name variable in the base class?
You couldn't have a member variable in a base that you don't want to be in the derived class.
You could for example use multiple inheritance so that you do have a base with the variable in some derived classes. Something like this:
struct Person {
unsigned int age;
virtual std::string name() = 0;
...
struct Named {
std::string name;
};
struct NamedPerson : Person, private Named {
std::string name() override {
return name;
}
};
struct JaredPerson : Person {
std::string name() override {
return "Jared";
}
};
Here, there is a base with the variable, but Jared does not inherit that particular base.

No.
Inheriting from a class means that you include all its member variables, it's parent class[s] member variables, plus whatever your own class contains.
To put it another way, child classes are a superset of parent classes. (with the exception of an empty child class)
Even private members are still there taking up space, it's just a compiler error to try and access them.

Can a derived class be smaller than its parent class?
In C++, No!
Even if you try to replace a member of the base class with a smaller member in the derived class (by using the same name), the base class member is still there (it's just harder to access). This code will demonstrate that, with the derived class actually adding to the size of the base:
#include <iostream>
class A {
public:
double q[200];
};
class B : A {
public:
double q[100]; // Can we replace base array with a smaller one?
};
int main()
{
std::cout << sizeof(A) << std::endl; // -> 1600 = 200 * sizeof(double)
std::cout << sizeof(B) << std::endl; // -> 2400 ADDS 100 more doubles!
return 0;
}

The answer should be clear if you make use of polymorphism. That is, take advantage of the language features that let you view an object of a derived type as one of a base type. Assume Person is a public base of PersonNamedJared and consider the following code.
PersonNamedJared Jared;
Person * Pointer = &Jared;
std::cout << Pointer->name << " is " << Pointer->age << " years old.";
This is valid, but how could this code possibly work if PersonNamedJared lacked a name field?
As a rule of thumb, if you have a legitimate reason to want a derived class to be smaller than its base class, then there is probably something wrong with your class design.
With regards to could there be a language that has this feature, I think it is possible, but rather awkward. You could – in a hypothetical language – blur the line between data members and function members by allowing the identifier name to represent (virtual) data in the base class but a function in derived classes. So a derived class could provide a function called name, overriding the base class version. You could block explicit references to the base class version of name when dealing with an object of derived type. With enough requirements and prohibitions, the name field would inaccessible in certain derived class objects, hence it would not be needed by them. In that case, the name field could be omitted. (However, I am not aware of any language that permits this stringent setup.)
On the other hand, this setup feels like it runs counter to the principles of inheritance. Even if a language allowed this setup, I would prefer better class design.

Related

Override pure virtual function with different parameter of derived type

There are a lot of questions about this topic, but however, I didn't find the solution for my following question:
I have the following classes:
1) The pure virtual class
class Employee {
private:
vector<Employee> vec_employee;
public:
Employee() {};
virtual ~Employee() {};
virtual void set_vec_subordinate(vector<Employee> vec_employee) = 0;
};
2) A derived class
class Worker : Employee{ private: public: };
3) Another derived class which should override the pure virtual method from Employee
class Manager : Employee {
private:
public:
inline void set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); };
};
What I try to achieve is to override the pure virtual method but use a "different" parameter. So still new to C++ but I think there should be a way to do so, especially because the other parameter is from type Worker which is a derived class from Employee.
There is no way to do exactly what you plan to do (and there is good reason for that).
Your code is also inherently broken, as you use the type vector<Employee>, which requires objects of type Employee - which cannot exist, as Employee is an abstract class. You may wish to use a vector of a reference type, e.g., vector<shared_ptr<Employee>> instead. (The rest of this answer glosses over this fact to make it more readable.)
Note also that void Manager::set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); }; would cause an infinite loop (probably resulting in a stack overflow) when called, as it will just keep calling itself.
The class Employee has a contract with its users, that says the following code must be valid (assuming given get_boss and get_workers functions):
Employee& boss = get_boss();
vector<Employee> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec);
Now, this might not make any semantic sense for your application, but the syntax of the programming language means that this must be possible. Some programming languages (not C++!) allow covariant calls similar to this:
Employee& boss = get_boss();
vector<Worker> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec); // Invalid C++: `vector<Worker` cannot be converted to `vector<Employee>` implicitly
While it is indeed possible to create a container in C++ that behaves in a way so that this use is possible, it is easier to deal with it is by making the set_vec_subordinate function a template that requires an arbitrary container of objects that are implicitly convertible or derived from Employee - and then just converting the objects during the copy operation (since the vector is not movable in that case anyway).
The second idea is that it should be possible to change the signature of a function when overriding it. This is kind of possible in C++ by implementing the base case (which needs to be binary compatible with - a.k.a. equal to - the signature of the Employee version, as it will be called for that case as well) and then adding additional overloads. For example, you could do something along the lines of:
class Manager : Employee {
private:
public:
inline void set_vec_subordinate(vector<Employee> vec_employee) override { this->vec_employee = std::move(vec_employee); };
inline void set_vec_subordinate(vector<Worker> const& vec_worker) {
vec_employee = std::vector<Employee>(vec_worker.begin(), vec_worker.end()); // copy convert all elements
};
};

In C++, are a new set of private variables created for a derived class?

This might be a stupid question but I've been thinking about it all day. When a derived class is created, is it using public members of the base class to act on its own private variables? To explain this better I wrote a quick program below
#include <iostream>
#include <string>
class person
{
public:
std::string getname(void) { return name; }
void setname(std::string x) { name = x; }
private:
std::string name;
int age;
};
class doubleperson :public person{};
int main()
{
person a, b;
doubleperson c;
a.setname("bob");
b.setname("jon");
c.setname("jim");
std::cout << a.getname() << std::endl;
std::cout << b.getname() << std::endl;
std::cout << c.getname() << std::endl;
std::cout << &c.getname() << std::endl;
std::cout << &a.getname() << std::endl;
std::cout << &b.getname() << std::endl;
std::cin.get();
When I run this code I get
bob
jon
jim
0032F904
0032F8E0
0032F8BC
Which tells me that there are three separate instances of the "name" variable. When I create a base class, does c.setname use setname in class person or class double person and how does it know to act on "name" from my derived class instead of the base class?
You're confusing access privledges with building an instance of a class.
When you declare a class, you are defining the structure of a new type. This can include member variables (and functions, etc.), and these would be created each time the class is created as an object. For example, if you created 3 different variables of class Person, each of these would have their own distinct memory for each of the member variables declared in the class definition. There are exceptions to this, such as static member variables, but in general each instance of a class will have its own memory space of each of its member variables.
Creating a subclass is just effectively extending an existing class into a new type that can include new member variables (and other related factors). The original memory definition of the parent class is still contained within the subclass. In this case, your doubleperson class contains the same information as the parent person class, namely each doubleperson class now has a member variable called "name". Hence, when you create an instance of each doubleperson class, you create a distinct location in memory for this member variable name and the other parts of the doubleperson class. This is of course why you see distinct memory locations in each of the instances. If you had declared the member variable name in the person class static, this would now make one variable shared across all instances of doubleperson (and person, for that matter), and then you would have seen each doubleperson instance having the same memory location for the member variable name.
This is also to say access privlidges of member variables is not reflective of how they are stored in a class definition. Access just defines at what level in the class hierarchy you can access a particular member variable. Here, the name variable can be accessed within functions of the person class but not the doubleperson subclass. But whenever you create an instance of the doubleperson class, you carry the definition of the person class along with it in its own distinct memory space. To modify how a particular member variable is stored in memory across instances, you need to look to keywords like "static" or other programming patterns to implement this type of functionality.
I think I see your confusion. A doubleperson object when constructed will still call the default constructor of the person class. A doubleperson is still a person but only has public access to its members. So using your getter and setters, a doubleperson object has access to the private variables of the person base object through the person object public methods it has access to.
Also, as was pointed out by StoryTeller in the comments above, your getname method returns by value (which is a temporary copy that gets destroyed. This should not compile with the proper warnings enabled). Instead you should return by reference if you really want the address to the name method (which helps facilitate your question as to the 3 separate addresses, but outside of this question would also be bad practice and break encapsulation).
It should be: (which as noted above only helps to illustrate the point of your question and is really bad practice because it breaks encapsulation)
std::string& getname(void) { return name; }

Abstract base member variable in base class

I want to specify an interface which requires an abstract class to have a certain type as a member variable.
I'll try to replicate the situation here:
class Blob {
int data[32];
};
class Worker {
string name;
abstract void workOn(Blob&) = 0;
}
class Abstract {
vector<shared_ptr<W>> workerList;
Blob allTheStuff;
abstract void somethingElse() = 0;
void doAllTheWork() {
for (w : workerList) {
w->workOn(allTheStuff);
}
}
};
class B_Blob : public Blob {
int moreData[4096];
};
class BulbasaurTrainingCamp : public Abstract {
B_Blob allTheStuff;
void somethingElse() {} // implemented
// this class will accept Bulbasaurs into workerList
};
class Bulbasaur : Worker {
Bulbasaur(): name("Fushigidane") {}
void workOn(Blob& b) {
// bulbasaurs cover *all* their workspace with crap
for (int i=0; i<sizeof(b.data[0])/sizeof(b.data); ++i) {
b.data[i] = *((int*)&("crap"));
}
for (i=0; i<sizeof(b.moreData[0])/sizeof(b.moreData); ++i) {
b.moreData[i] = *((int*)&("crap"));
}
}
Here, the abstract bas class has a Blob, but the instance of BulbasaurTrainingCamp has a derived B_Blob. It appears that since I gave it the same name, the compiler accepts it.
Is there a name for this? What I want to know is what the behavior is when I do this. Have I overridden the Blob with the B_Blob?
I am basically not sure about whether there is an inaccessible base Blob instance hanging around inside of BulbasaurTrainingCamp. My expectation is that each Bulbasaur will write 16512 (not 16384) bytes of crap across the two member variables of B_Blob. I am hoping that C++ will actually do what appears to be the sensible thing. It's a case of, "it compiles so I think I should be happy, but I'm still not totally sure it's doing what I think it should be doing".
#include<iostream>
#include<vector>
using namespace std;
int main()
{
class base
{
public:
int sameName;
base(int x):sameName(x){}
};
class derived : public base
{
public:
int diffName;
int sameName;
derived(int x,int i,int j):base(x),diffName(i),sameName(j){}
};
derived example(1,2,3);
cout<<example.sameName<<endl;
cout<<example.diffName<<endl;
cout<<example.base::sameName<<endl;
}
The result is 3 2 1.
I hope the example could be helpful.
A base class, even an abstract one, will be included in its entirety within any derived classes. The new allTheStuff name hides the old one, but does not suppress its inclusion; the base class version can still be accessed using Abstract::allTheStuff. Worse, the function doAllTheWork will end up accessing the base class allTheStuff because it can't possibly know there's an identically-named member variable in a subclass.
If you want this kind of behaviour, you have a few decent options:
Don't put any meaningful code or data in the base class; leave it as a pure interface. This may result in code duplication (but you may be able to factor it out into new base classes or shared helper functions).
Use a dynamically sizable container type as the Blob, so you can dynamically ask for more or less space in the constructor.
Make Blob a separate inheritance hierarchy (e.g. B_Blob and S_Blob inherit from an abstract Blob with differing amounts of space allocated), with a virtual function in Abstract that returns the Blob to use.
You seem to be somehow assuming that this code compiles using C++. It certainly doesn't. Even after patching about various of the C++/CLI specifics, it remains that a Blob does not have a data member called moreData and the only way to get at it (using C++) is to use a suitable cast.
The BulbasaurTrainingCamp objects will have two members called allTheStuff, one of type Blob and one of type B_Blob. Which one you get depends on which type you are looking at (since all members are private, you won't get any, but let's ignore that detail) and/or which qualification you use:
BulbasaurTrainignCamp btc;
B_Blob& b_blob = bts.allTheStuff;
Blob& blob1 = bts.Abstract::allTheStuff;
Abstract& abstract;
Blob& blob2 = abstract.allTheStuff;
That is, when using something which looks like a BulbasaurTrainingCamp you can access both the Blob and the B_Blob objects but you need to use qualification to access Abstracts allTheStuff member. When using an Abstract you can only access Abstracts Blob object.

Accessing a protected member of a superclass-typed member object - an elegant solution

First off, I know I can not do it, and I think it's not a duplicate questions (this and this questions deal with the same problem, but they only want an explanation of why it does not work).
So, I have a similar concept of classes and inheritance and I would, somehow, elegantly, want to do something that's forbidden. Here's a very simple code snippet that reflects what I want to do:
#include <iostream>
class A{
protected:
int var;
std::vector <double> heavyVar;
public:
A() {var=1;}
virtual ~A() {}
virtual void func() {
std::cout << "Default behavior" << this->var << std::endl;
}
// somewhere along the way, heavyVar is filled with a lot of stuff
};
class B: public A{
protected:
A* myA;
public:
B(A &a) : A() {
this->myA = &a;
this->var = this->myA->var;
// copy some simple data, e.g. flags
// but don't copy a heavy vector variable
}
virtual ~B() {}
virtual void func() {
this->myA->func();
std::cout << "This class is a decorator interface only" << std::endl;
}
};
class C: public B{
private:
int lotsOfCalc(const std::vector <double> &hv){
// do some calculations with the vector contents
}
public:
C(A &a) : B(a) {
// the actual decorator
}
virtual ~C() {}
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->myA->heavyVar); // illegal
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
}
};
int main(void){
A a;
B b(a);
C c(a);
a.func();
b.func();
c.func();
return 0;
}
The reason for doing this is that I'm actually trying to implement a Decorator Pattern (class B has the myA inner variable that I want to decorate), but I would also like to use some of the protected members of class A while doing the "decorated" calculations (in class B and all of it's subclasses). Hence, this example is not a proper example of a decorator (not even a simple one). In the example, I only focused on demonstrating the problematic functionality (what I want to use but I can't). Not even all the classes/interfaces needed to implement a Decorator pattern are used in this example (I don't have an abstract base class interface, inherited by concrete base class instances as well as an abstract decorator intreface, to be used as a superclass for concrete decorators). I only mention Decorators for the context (the reason I want a A* pointer).
In this particular case, I don't see much sense in making (my equivalent of) int var public (or even, writing a publicly accessible getter) for two reasons:
the more obvious one, I do not want the users to actually use the information directly (I have some functions that return the information relevant to and/or written in my protected variables, but not the variable value itself)
the protected variable in my case is much more heavy to copy than an int (it's a 2D std::vector of doubles), and copying it in to the instance of a derived class would be unnecessarily time- and memory-consuming
Right now, I have two different ways of making my code do what I want it to do, but I don't like neither of them, and I'm searching for a C++ concept that was actually intended for doing something of this sort (I can't be the first person to desire this behavior).
What I have so far and why I don't like it:
1. declaring all the (relevant) inherited classes friends to the base class:
class A{
....
friend class B;
friend class C;
};
I don't like this solution because it would force me to modify my base class every time I write a new subclass class, and this is exactly what I'm trying to avoid. (I want to use only the 'A' interface in the main modules of the system.)
2. casting the A* pointer into a pointer of the inherited class and working with that
void B::func(){
B *uglyHack = static_cast<B*>(myA);
std::cout << uglyHack->var + 1 << std::endl;
}
The variable name is pretty suggestive towards my feelings of using this approach, but this is the one I am using right now. Since I designed this classes, I know how to be careful and to use only the stuff that is actually implemented in class A while treating it as a class B. But, if somebody else continues the work on my project, he might not be so familiar with the code. Also, casting a variable pointer in to something that I am very well aware that it is not just feels pure evil to me.
I am trying to keep this projects' code as nice and cleanly designed as possible, so if anybody has any suggestions towards a solution that does not require the modification of a base class every now and then or usage of evil concepts, I would very much appreciate it.
I do believe that you might want to reconsider the design, but a solution to the specific question of how can I access the member? could be:
class A{
protected:
int var;
static int& varAccessor( A& a ) {
return a.var;
}
};
And then in the derived type call the protected accessor passing the member object by reference:
varAccessor( this->myA ) = 5;
Now, if you are thinking on the decorator pattern, I don't think this is the way to go.
The source of the confusion is that most people don't realize that a type has two separate interfaces, the public interface towards users and the virtual interface for implementation providers (i.e. derived types) as in many cases functions are both public and virtual (i.e. the language allows binding of the two semantically different interfaces). In the Decorator pattern you use the base interface to provide an implementation. Inheritance is there so that the derived type can provide the operation for the user by means of some actual work (decoration) and then forwarding the work to the actual object. The inheritance relationship is not there for you to access the implementation object in any way through protected elements, and that in itself is dangerous. If you are passed an object of a derived type that has stricter invariants regarding that protected member (i.e. for objects of type X, var must be an odd number), the approach you are taking would let a decorator (of sorts) break the invariants of that X type that should just be decorated.
I can't find any examples of the decorator pattern being used in this way. It looks like in C++ it's used to decorate and then delegate back to the decoratee's public abstract interface and not accessing non-public members from it.
In fact, I don't see in your example decoration happening. You've just changed the behavior in the child class which indicates to me you just want plain inheritance (consider that if you use your B to decorate another B the effects don't end up chaining like it would in a normal decoration).
I think I found a nice way to do what I want in the inheritance structure I have.
Firstly, in the base class (the one that is a base for all the other classes, as well as abstract base class interface in the Decorator Pattern), I add a friend class declaration only for the first subclass (the one that would be acting as abstract decorator interface):
class A{
....
friend class B;
};
Then, I add protected access functions in the subclass for all the interesting variables in the base class:
class B : public A{
...
protected:
A *myA;
int getAVar() {return myA->var;}
std::vector <double> &getAHeavyVar {return myA->heavyVar;}
};
And finally, I can access just the things I need from all the classes that inherit class B (the ones that would be concrete decorators) in a controlled manner (as opposed to static_cast<>) through the access function without the need to make all the subclasses of B friends of class A:
class C : public B{
....
public:
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->getAHeavyVar); // legal now!
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
std::cout << "And also the int: " << this->getAVar << std::endl;
// this time, completely legal
}
};
I was also trying to give only certain functions in the class B a friend access (declaring them as friend functions) but that did not work since I would need to declare the functions inside of class B before the friend declaration in class A. Since in this case class B inherits class A, that would give me circular dependency (forward declaration of class B is not enough for using only friend functions, but it works fine for a friend class declaration).

When do programmers use Empty Base Optimization (EBO)

I was reading about Empty Base Optimization(EBO). While reading, the following questions popped up in my mind:
What is the point of using Empty class as base class when it contributes nothing to the derived classes (neither functionality-wise, nor data-wise)?
In this article, I read this:
//S is empty
class struct T : S
{
      int x;
};
[...]
Notice that we didn’t lose any data or
code accuracy: when you create a
standalone object of type S, the
object’s size is still 1 (or more) as
before; only when S is used as base
class of another class does its memory
footprint shrink to zero. To realize
the impact of this saving, imagine a
vector that contains 125,000
objects. The EBO alone saves half a
megabyte of memory!
Does it mean that if we don't use "S" as base class of "T", we would necessarily consume double of megabyte of memory? I think, the article compares two different scenarios which I don't think is correct.
I would like to know a real scenario when EBO can proven to be useful.(means, in the same scenario, we would necessarily be at loss IF we don't use EBO!).
Please note that if your answer contains explanations like this :
The whole point is that an empty class has non-zero size, but when derived or deriving it can have zero size, then I'm NOT asking that, as I know that already. My question is, why would anyone derive his class from an empty class in the first place? Even if he doesn't derive and simply writes his class (without any empty base), is he at loss in ANY way?
EBO is important in the context of policy based design, where you generally inherit privately from multiple policy classes. If we take the example of a thread safety policy, one could imagine the pseudo-code :
class MTSafePolicy
{
public:
void lock() { mutex_.lock(); }
void unlock() { mutex_.unlock(); }
private:
Mutex mutex_;
};
class MTUnsafePolicy
{
public:
void lock() { /* no-op */ }
void unlock() { /* no-op */ }
};
Given a policy based-design class such as :
template<class ThreadSafetyPolicy>
class Test : ThreadSafetyPolicy
{
/* ... */
};
Using the class with a MTUnsafePolicy simply add no size overhead the class Test : it's a perfect example of don't pay for what you don't use.
EBO isn't really an optimization (at least not one that you do in the code). The whole point is that an empty class has non-zero size, but when derived or deriving it can have zero size.
This is the most usual result:
class A { };
class B { };
class C { };
class D : C { };
#include <iostream>
using namespace std;
int main()
{
cout << "sizeof(A) + sizeof(B) == " << sizeof(A)+sizeof(B) << endl;
cout << "sizeof(D) == " << sizeof(D) << endl;
return 0;
}
Output:
sizeof(A) + sizeof(B) == 2
sizeof(D) == 1
To the edit:
The optimization is, that if you actually do derive (for example from a functor, or from a class that has only static members), the size of your class (that is deriving) won't increase by 1 (or more likely 4 or 8 due to padding bytes).
The "Optimization" in the EBO means the case when you use base class can be optimized to use less memory than if you use a member of the same type. I.e. you compare
struct T : S
{
int x;
};
with
struct T
{
S s;
int x;
};
not with
struct T
{
int x;
};
If your question is why would you have an empty class at all (either as a member, or as a base), it is because you use its member functions. Empty means it has no data member, not that it does not have any members at all. Things like this are often done when programming with templates, where the base class is sometimes "empty" (no data members) and sometimes not.
Its used when programmers want to expose some data to client without increasing the client class size. The empty class can contain enums and typedefs or some defines which the client can use.The most judicious way to use such a class it it to,inherit such a class privately. This will hide the data from outside and wil not increase your class size.
There can be empty classes which do not have any member variables, but member functions (static or non static) which can act as utility classes, lets call this EmptyClass. Now we can have a case where we want to create a class (let's call it SomeClass) which have a containment kind of relation with EmptyClass, but not 'is-a' relation. One way is to create a member object of type EmptyClass in SomeClass as follows:
class EmptyClass
{
public:
void someFun1();
static int someUtilityFun2();
};
//sizeof(EmptyClass) = 1
class SomeClass
{
private:
EmptyClass e;
int x;
};
//sizeof(SomeClass) = 8
Now due to some alignment requirements compilers may add padding to SomeClass and its size is now 8 bytes. The better solution is to have a SomeClass derive privately from EmptyClass and in this way SomeClass will have access to all member functions of EmptyClass and won't increase the extra size by padding.
class SomeClass : private EmptyClass
{
private:
int x;
}
//sizeof(SomeClass) = 4
Most of the time, an empty base class is either used polymorphically (which the article mentions), as "tag" classes, or as exception classes (although those are usually derived from std::exception, which is not empty). Sometimes there is a good reason to develop a class hierarchy which begins with an empty base class.
Boost.CompressedPair uses the EBO to shrink the size of objects in the event that one of the elements is empty.
EASTL has a good explanation as to why they needed EBO, its also explained in-depth in the paper they link to/credit
EBO is not something the programmer influences, and/or the programmer would be punished for if (s)he chose not to derive from an empty base class.
The compiler controls whether for:
class X : emptyBase { int X; };
class Y { int x };
you get sizeof(X) == sizeof(Y) or not. If you do, the compiler implements EBO, if not, it doesn't.
There never is any situation where sizeof(Y) > sizeof(X) would occur.
The primary benefit I can think of is dynamic_cast. You can take a pointer to S and attempt to dynamic_cast it to anything that inherits from S- assuming that S offers a virtual function like a virtual destructor, which it pretty much must do as a base class. If you were, say, implementing a dynamically typed language, you may well wish or need for every type to derive from a base class purely for the purposes of type-erased storage, and type checking through dynamic_cast.