Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Request for Simple C++ Composition vs. Inheritance Examples

I am trying to understand the syntactic difference between composition and inheritance in C++.

I'm hoping someone will provide two simple examples. One example of a class that uses composition and one of a class that uses inheritance.

like image 704
LuminousNutria Avatar asked Apr 18 '18 03:04

LuminousNutria


People also ask

What is the difference between composition and inheritance explain with example?

Whereas inheritance derives one class from another, composition defines a class as the sum of its parts. Classes and objects created through inheritance are tightly coupled because changing the parent or superclass in an inheritance relationship risks breaking your code.

How do you decide between inheritance and composition?

Inheritance is an "is-a" relationship. Composition is a "has-a". You do composition by having an instance of another class C as a field of your class, instead of extending C . A good example where composition would've been a lot better than inheritance is java.

What is one specific example where you should use composition instead of inheritance?

The main difference between inheritance and composition is in the relationship between objects. Inheritance: “is a.” E.g. The car is a vehicle. Composition: “has a.” E.g. The car has a steering wheel.

Which one is preferable inheritance or composition and why?

One more benefit of composition over inheritance is testing scope. Unit testing is easy in composition because we know what all methods we are using from another class. We can mock it up for testing whereas in inheritance we depend heavily on superclass and don't know what all methods of superclass will be used.


2 Answers

Sure, why not? Since I like robots, let's make a robot that can walk around and grab things. We'll make one robot using inheritance, and another robot using composition:

class Legs
{
public:
   void WalkAround() {... code for walking around goes here...}
};

class Arms
{
public:
   void GrabThings() {... code for grabbing things goes here...}
};

class InheritanceRobot : public Legs, public Arms
{
public:
   // WalkAround() and GrabThings() methods are implicitly
   // defined for this class since it inherited those
   // methods from its two superclasses
};

class CompositionRobot
{
public:
   void WalkAround() {legs.WalkAround();}
   void GrabThings() {arms.GrabThings();}

private:
   Legs legs;
   Arms arms;
};

Note that at least for this example, the CompositionRobot is usually considered to be the better approach, since inheritance implies an is-a relationship, and a robot isn't a particular kind of Arms and a robot isn't a particular kind of Legs (rather a robot has-arms and has-legs).

like image 199
Jeremy Friesner Avatar answered Sep 28 '22 10:09

Jeremy Friesner


To expand a little on @jeremy-friesner's answer (and mostly reuse his code), a lot of the time composition is implemented using more classes than that. Essentially the Legs and Arms classes would be implementations of an interface. This makes it easy to inject those dependencies and, hence, mock/stub them out when unit testing the composite object. Then you'd have something like (ignoring virtual destructor...) :

class Walker // interface
{
public:
    virtual void Walk() = 0;
}

class Legs : public Walker
{
public:
    void Walk() {... code for walking around goes here...}
}

class Grabber // Interface
{
public:
    virtual void GrabThings() = 0;
}

class Arms : public Grabber
{
public:
    void GrabThings() {... code for grabbing things goes here...}
}

class InheritanceRobot : public Legs, public Arms
{
public:
    // Walk() and GrabThings() methods are implicitly
    // defined for this class since it inherited those
    // methods from its two superclasses
};

class CompositionRobot
{
public:
    CompositionRobot(Walker& walker, Grabber& grabber) 
        : legs(walker), 
          arms(grabber) 
    {} 
    void Walk() {legs.Walk();}
    void GrabThings() {arms.GrabThings();}

private:
    Walker& legs;
    Grabber& arms;
};

So the actual implementation used for legs and arms could be set at run-time instead of compile time.

As an aside, I only wrote this as an answer, rather than a comment on Jeremy's answer, to benefit from the code formatting so, if you feel like up-voting it, please do Jeremy's too.

HTH

UPDATE Sep 14, 2021:

One thing I've noticed in this answer is that I've conflated composition and aggregation. In composition, if the parent object ceases to exist, then so does the child object whereas, in aggregation, the child objects may exist after the parent is destroyed. The description I've given, where references to instances of the child objects are passed in the CompositionRobot constructor implies an aggregation relationship rather than composition. However, if you were to use std::unique_ptr() when defining the parameters and creating the objects, and std::move() when they're stored in the constructor of CompositionRobot, the effect would be much the same as in Jeremy's answer where the objects (rather than a pointer or a reference to them) are defined as class members.

like image 37
cosimo193 Avatar answered Sep 28 '22 10:09

cosimo193