Multiple Inheritance
Copy Constructor
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
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
#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;
}
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
#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;
}
A constructor is called when a new object is created "from scratch"
Examples:
className objectName1;
className objectName(arguments);
className *p = new objectName;
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);
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);
#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;
}
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)
#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;
}