diamond problem

The diamond problem occurs when two superclasses of a class have a common base class. For example, the TA class gets two copies of all attributes of Person class, this causes ambiguities.
```
#include <iostream>
using namespace std;

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

int main()  {
    TA ta;
    return 0;
}
```
Output is,
```
Person::Person()
Faculty::Faculty()
Person::Person()
Student::Student()
TA::TA()
```
In the above program, constructor of ‘Person’ is called two times. Destructor of ‘Person’ will also be called two times when object ‘ta’ is destructed. So object ‘ta’ has two copies of all members of ‘Person’, this causes ambiguities. The solution to this problem is ‘virtual’ keyword. We make the classes ‘Faculty’ and ‘Student’ as virtual base classes to avoid two copies of ‘Person’ in ‘TA’ class. For example, consider the following program.
```
#include <iostream>
using namespace std;

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

int main()  {
    TA ta;
    return 0;
}
```
Output:
```
Person::Person()
Faculty::Faculty()
Student::Student()
TA::TA()
```
In Python, the diamond problem is not a issue cause constructors are overwrited.
```
class A:
    def __init__(self):
        print("A")
 
 
class B(A):
    def __init__(self):
        super().__init__()
        print("B")
 
 
class C(A):
    def __init__(self):
        super().__init__()
        print("C")
 
 
class D(B, C):
    def __init__(self):
        super().__init__()
        print("D")
        
o = D()
```
Output:
```
A
C
B
D
```