Рубрики

Множественное наследование в C ++

Множественное наследование — это особенность C ++, где класс может наследовать от нескольких классов.

Конструкторы унаследованных классов вызываются в том же порядке, в котором они наследуются. Например, в следующей программе конструктор B вызывается перед конструктором A.

#include<iostream>

using namespace std;

  

class A

{

public:

  A()  { cout << "A's constructor called" << endl; }

};

  

class B

{

public:

  B()  { cout << "B's constructor called" << endl; }

};

  

class C: public B, public // Обратите внимание на порядок

{

public:

  C()  { cout << "C's constructor called" << endl; }

};

  

int main()

{

    C c;

    return 0;

}

Выход:

B's constructor called
A's constructor called
C's constructor called

Деструкторы вызываются в обратном порядке конструкторов.

Алмазная проблема
Проблема алмазов возникает, когда два суперкласса класса имеют общий базовый класс. Например, на следующей диаграмме класс TA получает две копии всех атрибутов класса Person, что вызывает неоднозначности.

Например, рассмотрим следующую программу.

#include<iostream>

using namespace std;

class Person {

   // Данные членов лица

public:

    Person(int x)  { cout << "Person::Person(int ) 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)   {

        cout<<"TA::TA(int ) called"<< endl;

    }

};

  

int main()  {

    TA ta1(30);

}

Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called

В приведенной выше программе конструктор Person вызывается два раза. Деструктор «Персона» также будет вызываться два раза при разрушении объекта «та1». Таким образом, объект «ta1» имеет две копии всех членов «Person», что вызывает неоднозначность. Решением этой проблемы является «виртуальное» ключевое слово . Мы делаем классы «Преподавательский» и «Студенческий» виртуальными базовыми классами, чтобы избежать двух копий «Персона» в классе «ТА». Например, рассмотрим следующую программу.

#include<iostream>

using namespace std;

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);

}

Выход:

Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called

В приведенной выше программе конструктор Person вызывается один раз. Одна важная вещь, которую следует отметить в вышеприведенном выводе, это то, что вызывается конструктор по умолчанию «Person» . Когда мы используем ключевое слово «virtual», конструктор по умолчанию класса grandparent вызывается по умолчанию, даже если родительские классы явно вызывают параметризованный конструктор.

Как вызвать параметризованный конструктор класса Person? Конструктор должен быть вызван в классе «TA». Например, см. Следующую программу.

#include<iostream>

using namespace std;

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);

}

Выход:

Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called

В общем случае нельзя напрямую вызывать конструктор дедушки, его нужно вызывать через родительский класс. Это разрешено только при использовании виртуального ключевого слова.

В качестве упражнения прогнозируем выход следующих программ.

Вопрос 1

#include<iostream>

using namespace std;

  

class A

{

  int x;

public:

  void setX(int i) {x = i;}

  void print() { cout << x; }

};

  

class B:  public A

{

public:

  B()  { setX(10); }

};

  

class C:  public A  

{

public:

  C()  { setX(20); }

};

  

class D: public B, public C {

};

  

int main()

{

    D d;

    d.print();

    return 0;

}

вопрос 2

#include<iostream>

using namespace std;

  

class A

{

  int x;

public:

  A(int i) { x = i; }

  void print() { cout << x; }

};

  

class B: virtual public A

{

public:

  B():A(10) {  }

};

  

class C:  virtual public

{

public:

  C():A(10) {  }

};

  

class D: public B, public C {

};

  

int main()

{

    D d;

    d.print();

    return 0;

}

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Множественное наследование в C ++

0.00 (0%) 0 votes