Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Inheritance


Contents

Multiple Inheritance

We can have a class derive from 2 classes.

File: multi1.cpp
#include <iostream>
using namespace std ;

// Base class
class BaseA
{
  public:
    void myFunctionBaseA()
    {
      cout << "Some content in parent class BaseA." << endl ;
    }
};

// Another base class
class BaseB
{
  public:
    void myFunctionBaseB()
    {
      cout << "Some content in parent class BaseB.." << endl ;
    }
};

// Derived class
class MyChildClass: public BaseA, public BaseB
{
};

int main()
{
  MyChildClass myObj;
  myObj.myFunctionBaseA()  ;
  myObj.myFunctionBaseB()  ;
  return 0;
}

Output:
$ rm a.exe ; g++ multi1.cpp ; ./a.exe
Some content in parent class BaseA.
Some content in parent class BaseB..

The diamond problem:
        class A
  class B     class C
         class D

class D inherits 2 copies of class A


File: multi2.cpp
#include<iostream>
using namespace std;

//The diamond problem

class Person {
// Data members of person
public:
    Person(int x) { cout << "Person::Person(int ) called" << endl; }
};

class Faculty : public Person {
// data members of Faculty
public:
    Faculty(int x):Person(x) {
    cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};

class Student : public Person {
// data members of Student
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};

class TA : public Faculty, public Student {
public:
    TA(int x):Student(x), Faculty(x) {
        cout<<"TA::TA(int ) called"<< endl;
    }
};

int main() {
    TA ta1(30);
}

$ rm a.exe ; g++ multi2.cpp ; ./a.exe
Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called

We can see that the constructor for Person gets
called twice.
Use the "virtual" on class to prevent 2 copies.

File: multi3.cpp
#include<iostream>
using namespace std;
//Default constructor called for multiple
//inheritance with virtual keyword.


class Person {
public:
    Person(int x) { cout << "Person::Person(int ) called" << endl; }
    Person()     { cout << "Person::Person() called" << endl; }
};

class Faculty : virtual public Person {
public:
    Faculty(int x):Person(x) {
    cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};

class Student : virtual public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};

class TA : public Faculty, public Student {
public:
    TA(int x):Student(x), Faculty(x) {
        cout<<"TA::TA(int ) called"<< endl;
    }
};

int main() {
    TA ta1(30);
}

$ rm a.exe ; g++ multi3.cpp ; ./a.exe
Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called

We notice that the default base class constructor
got called instead of the the one with the argument.
What if we didn't have a default base class constructor ?
Then we get a compiler error of the form:

multi3.cpp: In constructor ‘TA::TA(int)’:
multi3.cpp:29:40: error: no matching function for call to ‘Person::Person()’
   29 |         TA(int x):Student(x), Faculty(x) {
      |

Calling the base class constructor when it has an argument.

File: multi4.cpp
#include<iostream>
using namespace std;

//Calling the base class constructor with argument

class Person {
public:
    Person(int x) { cout << "Person::Person(int ) called" << endl; }
    Person()     { cout << "Person::Person() called" << endl; }
};

class Faculty : virtual public Person {
public:
    Faculty(int x):Person(x) {
    cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};

class Student : virtual public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};

class TA : public Faculty, public Student {
public:
    TA(int x):Student(x), Faculty(x), Person(x) {
        cout<<"TA::TA(int ) called"<< endl;
    }
};

int main() {
    TA ta1(30);
}

Output:
$ rm a.exe ; g++ multi4.cpp ; ./a.exe
rm: cannot remove 'a.exe': No such file or directory
Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called

We need to make the change in the constructor for the
bottom most class which is "TA" in this case.

TA(int x):Student(x), Faculty(x), Person(x)
The above only works for virtual derived classes. We are not referring to a virtual function here but when the virtual keyword in defining the class.

File: multi5.cpp
#include<iostream>
using namespace std;

//Calling the base class constructor with argument
//will not compile for non virtual cases
class Person {
public:
    Person(int x) { cout << "Person::Person(int ) called" << endl; }
    Person()     { cout << "Person::Person() called" << endl; }
};


class Faculty :  public Person {
public:
    Faculty(int x):Person(x) {
    cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};

class Student :  public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};

class TA : public Faculty, public Student {
public:
    TA(int x):Student(x), Faculty(x), Person(x) {
        cout<<"TA::TA(int ) called"<< endl;
    }
};

int main() {
    TA ta1(30);
}


$ rm a.exe ; g++ multi5.cpp ; ./a.exe
multi5.cpp: In constructor ‘TA::TA(int)’:
multi5.cpp:29:43: error: type ‘Person’ is not a direct base of ‘TA’
   29 |         TA(int x):Student(x), Faculty(x), Person(x) {
      |                                           ^~~~~~
bash: ./a.exe: No such file or directory