Composition versus inheritance

The C++ language provides us with convenient and OOP-friendly syntax so that we can express the inheritance relationship, but the way the compiler processes it resembles composition rather than inheritance. It's actually even better to use composition instead of inheritance wherever it is applicable. The Square class and its relationship with the Rectangle was claimed to be a bad design choice. One of the reasons was the subtype substitution principle, which allowed us to use the Square the wrong way: pass it to a function that modifies it as a Rectangle rather than a Square. This tells us that the is-a relationship is not correct because the Square is not a Rectangle after all. It is an adaptation of a Rectangle rather than a Rectangle itself, which means it doesn't actually represent a Rectangle; it uses it to provide limited functionality to class users.

Users of the Square shouldn't know that it can be used as a Rectangle; otherwise, at some point, they would send invalid or unsupported messages to Square instances. Examples of invalid messages are the calls to the set_width or set_height function. The Square shouldn't actually support two different member functions to modify its sides separately, but it can't hide this because it announced that it's inherited from the Rectangle:

class Square : public Rectangle {
// code omitted for brevity
};

What if we change the modifier from public to private? Well, C++ supports both public and private inheritance types. It also supports protected inheritance as well. When inheriting privately from a class, the subclass intends to use the parent class and has access to its public interface. However, the client code is not aware that it deals with a derived class. Furthermore, the public interface that's inherited from the parent class becomes private for users of the child class. It seems like the Square transforms inheritance into a composition:

class Square : private Rectangle {
public:
void set_side(int side) {
// Rectangle's public interface is accessible to the Square
set_width(side);
set_height(side);
}
int area() {
area_ = Rectangle::area();
return area_;
}
private:
int area_;
};

The client code cannot access members inherited from the Rectangle:

Square sq;
sq.set_width(14); // compile error, the Square has no such public member
make_big_rectangle(sq); // compile error, can't cast Square to Rectangle

The same can be achieved by declaring a Rectangle member in the private section of the Square:

class Square {
public:
void set_side(int side) {
rectangle_.set_width(side);
rectangle_.set_height(side);
}
int area() {
area_ = rectangle_.area();
return area_;
}
private:
Rectangle rectangle_;
int area_;
};

You should carefully analyze usage scenarios and completely answer the is-a question in order to use inheritance without a doubt. Every time you encounter a choice between composition and inheritance, choose composition.

We can omit the modifier when inheriting privately. The default access modifier for classes is private, so class Square : private Rectangle {}; is the same as class Square : Rectangle {};. On the contrary, the default modifier for structs is public.