В множественном наследовании (ромбовидная форма) конструктор по умолчанию для родительского объекта называется

#include<iostream>
using namespace std;
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);
}

O / P:

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

В приведенной выше форме ромба два родительских класса наследуются от прародителя с виртуальным ключевым словом, поэтому конструктор класса Person вызывается только один раз. Но почему здесь вызывается конструктор по умолчанию для прародителя? Может кто-нибудь сказать мне точную причину
Большое спасибо

-4

Решение

TA это Personтак что в этом нет ничего неожиданного Personконструктор называется. Если вы использовали виртуальное наследование, как вы утверждали, ваш TA класс будет иметь один Person подобъекта, поэтому следует ожидать тот факт, что его конструктор вызывается один раз. Если вы не использовали виртуальное наследование, TA будет два Person подобъекты, и вы могли ожидать два Person вызов конструктора.

2

Другие решения

Конфигурации Diamond требуют виртуальных базовых классов, или вы собираетесь получить двуличие в представлении объектов.

class A
{
}

class B : virtual public A
{
};

class C : virtual public A
{
}

class D: public B, public C
{
}

Это гарантирует, что только одно представление A превращает его в конечный объект типа D, и оно будет доступно всем.

Я оставляю это в качестве упражнения для спрашивающего, как передать параметры конструктора через это. это не интуитивно понятный, но Google + «виртуальный базовый класс» будет более чем поучительно.

1

C ++ Faq отвечает на ваш вопрос красиво:

[25.12] Какие особые соображения мне нужно знать, когда я наследую от класса, который использует виртуальное наследование?

Список инициализации ctor большинства производных классов напрямую вызывает ctor виртуального базового класса.

Поскольку подобъект виртуального базового класса встречается в экземпляре только один раз, существуют специальные правила, обеспечивающие, чтобы конструктор и деструктор виртуального базового класса вызывались ровно один раз для каждого экземпляра. Правила C ++ говорят, что виртуальные базовые классы создаются раньше всех не виртуальных базовых классов. Вам, как программисту, нужно знать следующее: конструкторы для виртуальных базовых классов в любой части иерархии наследования вашего класса вызываются конструктором самого производного класса.

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

Однако, если автор виртуального базового класса следовал рекомендациям из предыдущего FAQ, тогда конструктор виртуального базового класса, вероятно, не принимает параметров, поскольку у него нет данных для инициализации. Это означает (к счастью!), Что авторам конкретных классов, которые в конечном итоге наследуют виртуальный базовый класс, не нужно беспокоиться о том, чтобы брать дополнительные параметры для передачи в ctor виртуального базового класса.

0
По вопросам рекламы [email protected]