BTP200

Multiple Inheritance and Copy Constructor

Summary

Multiple Inheritance

Copy Constructor

Multiple Inheritance

Introduction

A child class can be derived from more than one parent

This means that the child class inherits member variables and member functions from both parent classes

Access is still controlled via access specifiers: private, protected, and public

Multiple Inheritance

Multiple Inheritance

To add multiple base classes, the syntax is:

class Child: public Parent1, public Parent2, ...

Note that the constructors and destructors will be called in the provided order

Multiple Inheritance

Example

#include <iostream>
const int N = 64;

class Father
{
protected:
    char last_name_[N] = "Vader";

public:
    Father() { std::cout << "Father class created"
                         << std::endl; }
    ~Father() { std::cout << "Father class destroyed"
                          << std::endl; }
};

class Mother
{
protected:
    char middle_name_[N] = "Naberrie";

public:
    Mother() { std::cout << "Mother class created"
                         << std::endl; }
    ~Mother() { std::cout << "Mother class destroyed"
                          << std::endl; }
};

class Child : public Father, public Mother
{
public:
    Child() { std::cout << "Child class created"
                        << std::endl; }
    ~Child() { std::cout << "Child class destroyed"
                         << std::endl; }
    void name() { std::cout << "My full name is Luke "
                            << middle_name_ << " "
                            << last_name_ << std::endl;}
};

int main()
{
    Child Luke;
    Luke.name();

    return 0;
}

              

Diamond Inheritance

Imagine two classes inheriting the same base class

Also, imagine that another class inherits from these two classes

In this scenario, called a diamond problem, the first class in inherited twice!

This leads to ambiguity and for constructors and destructors to be called twice

Use virtual inheritance and namespaces to solve these issues

Diamond Inheritance

Example

#include <iostream>
const int N = 64;

class Grandfather
{
protected:
    int age = 80;

public:
    Grandfather() { std::cout << "Grandfather created"
                              << std::endl; }
    ~Grandfather() { std::cout << "Grandfather destroyed"
                               << std::endl; }
};

class Father : virtual public Grandfather
{
protected:
    char last_name[N] = "Vader";

public:
    Father() { std::cout << "Father class created"
                         << std::endl; }
    ~Father() { std::cout << "Father class destroyed"
                          << std::endl; }
};

class Mother : virtual public Grandfather
{
protected:
    char middle_name[N] = "Naberrie";

public:
    Mother() { std::cout << "Mother class created"
                         << std::endl; }
    ~Mother() { std::cout << "Mother class destroyed"
                          << std::endl; }
};

class Child : public Father, public Mother
{
public:
    Child() { std::cout << "Child class created"
                        << std::endl; }
    ~Child() { std::cout << "Child class destroyed"
                         << std::endl; }
    void name() { std::cout << "My full name is Luke "
                            << middle_name << " "
                            << last_name << std::endl; }
    void print() { std::cout << age << std::endl; }
};

int main()
{
    Child Luke;
    Luke.name();

    std::cout << std::endl;

    return 0;
}

              

Copy Constructor

Calling Constructors

A constructor is called when a new object is created "from scratch"

Examples:

className objectName1;
className objectName(arguments);
className *p = new objectName;

Copy Constructors

A copy constructor is called when a new object is created "from another object". This happens when:

  1. An object is created with an assignement

className objectName = otherObject;

  2. An object is passed to a function by value

void function(className objectName);

Copy Constructors ctd.

  3. An object is returned from a function by value

className function(arguments);

  4. An object is passed as argument to the constructor

className objectName(otherObject);

Copy Constructors

Example

#include <iostream>

class MyClass
{
private:
    int num;

public:
    // Parameterized constructor
    MyClass(){
        num = 0;
    }
    MyClass(int value)
    {
        num = value;
        std::cout << "Constructor called with: "
                  << num << std::endl;
    }
    // Copy constructor
    MyClass(const MyClass &other)
    {
        num = other.num + 1;
        std::cout << "Copy constructor called. Value: "
                  << num << std::endl;
    }
    ~MyClass()
    {
        std::cout << "Destructor called."
                  << std::endl;
    }
    void display() const
    {
        std::cout << "Value: " << num << std::endl;
    }
};

void display(MyClass obj)
{
    obj.display();
}

MyClass xerox(MyClass obj)
{
    return obj;
}

int main()
{
    // Parametrized constructor
    MyClass obj1(10);
    obj1.display();

    // Copy constructor
    MyClass obj2 = obj1;
    obj2.display();

    // Another call to copy constructor
    MyClass obj3(obj2);
    obj3.display();

    // Yet another call to copy constructor
    display(obj3);

    // Two calls to copy constructors!
    MyClass obj4 = xerox(obj3);
    obj4.display();

    MyClass obj5 = obj4;

    return 0;
}

              

Inheritance and Copy Constructors

For a derived class copy constructor to call a base copy constructor, one needs to specify it

The syntax for doing it is:

derivedClass(const derivedClass &obj) : baseClass(obj)

Copy Constructors

Example

#include <iostream>

class baseClass
{
protected:
    int num;

public:
    // Parameterized constructor
    baseClass(int value)
    {
        num = value;
        std::cout << "Base Constructor called."
                  << std::endl;
    }
    // Copy constructor
    baseClass(const baseClass &other)
    {
        num = other.num + 1;
        std::cout << "Base Copy constructor called."
                  << std::endl;
    }
    ~baseClass()
    {
        std::cout << "Destructor called."
                  << std::endl;
    }
    void display() const
    {
        std::cout << "Value: " << num << std::endl;
    }
};

class derClass : public baseClass
{
public:
    // Parameterized constructor
    derClass(int value) : baseClass(value)
    {
        std::cout << "Derived Constructor called."
                  << std::endl;
    }
    // Copy constructor calling base copy constructor
    derClass(const derClass &other) : baseClass(other)
    {
        std::cout << "Base Copy constructor called."
                  << std::endl;
    }
    ~derClass()
    {
        std::cout << "Destructor called."
                  << std::endl;
    }
    void display() const
    {
        std::cout << "Value: " << num << std::endl;
    }
};

int main()
{
    // Parametrized constructor
    derClass obj1(10);
    obj1.display();

    // Copy constructor
    derClass obj2 = obj1;
    obj2.display();

    // Another call to copy constructor
    derClass obj3(obj2);
    obj3.display();

    return 0;
}

              

Suggested Reading

Multiple Inheritance

Copy Constructors