OOP · Objects & interfaces
Inheritance
Reuse a shared interface and behavior while keeping the relationship honest.
Build on a shared base.
Public inheritance lets a derived class build on a base class’s interface and implementation. A Dog can reuse Animal’s eat behavior and add fetch. Each Dog contains an Animal base part, so code expecting an Animal reference can also work with that Dog.
Write against a common interface.
A feeding function can accept Animal& when it only needs Animal’s eat operation. Callers can supply a Dog or Cat without duplicating that function. Public inheritance promises that the derived object can sensibly be used through the base interface; shared code alone is not always a good reason to inherit.
void feed(Animal& animal) {
animal.eat();
}
Dog dog;
feed(dog);Dog gets its own Animal base part.
eat is inherited from Animal. Calling dog.eat() updates the energy in this dog’s base part. Cat objects would have their own base parts; inheriting does not create one global shared energy value.
struct Animal {
int energy = 0;
void eat() { ++energy; }
};
struct Dog : public Animal {
void fetch() { --energy; }
};
Dog dog;
dog.eat(); // energy is 1An “is an” relationship.
Dog and Cat are derived types. Each object has its own Animal base part. Public inheritance lets their references be used where an Animal reference is expected; it does not make every derived-only operation part of Animal’s interface.
- Animal
- eat()
- Dog
- adds fetch()
- Cat
- adds climb()
- Dog leads to Animal (is an)
- Cat leads to Animal (is an)
A Car has an Engine.
A Car contains an Engine; it is not itself an Engine. A member object expresses this relationship without promising that a Car supports the complete Engine interface. Use inheritance for an appropriate substitutable base relationship, and composition for parts that an object has.
struct Engine { void start(); };
struct Car {
Engine engine;
void drive() { engine.start(); }
};Further reading
Trusted resources for the rules and APIs discussed in this guide.