Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Вивчайте Діамантове Наслідування | Огляд Наслідування
C++ ООП
course content

Зміст курсу

C++ ООП

C++ ООП

1. Основи ООП у C++
2. Конструктори та Деструктори
3. Огляд Інкапсуляції
4. Огляд Наслідування
5. Огляд Поліморфізму

book
Діамантове Наслідування

Множинне наслідування може призвести до ситуації, відомої як проблема ромба або ромбовидне наслідування, що є суттєвою складністю в мовах об'єктно-орієнтованого програмування, які підтримують множинне наслідування.

Це виникає, коли підклас наслідується від двох або більше classes, які самі наслідуються від спільного базового класу. Термін ромб використовується тому, що схема наслідування нагадує форму ромба.

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};

Основна проблема ромбовидного наслідування — це неоднозначність, яку воно створює. Оскільки Diamond наслідується як від Derived1, так і від Derived2, які, у свою чергу, наслідуються від Base, в об'єкті класу Base існують дві копії Diamond. Це може призвести до неоднозначності.

main.cpp

main.cpp

copy
12345678910111213141516
#include <iostream> class Base { public: void display() { std::cout << "Base display()" << std::endl; } }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

Розв'язання проблеми

Ключове слово virtual допомагає уникнути цієї проблеми. Ви можете вирішити цю неоднозначність за допомогою віртуального наслідування, використовуючи ключове слово virtual. Коли Diamond наслідує віртуально, C++ гарантує, що існує лише одна копія суперкласу, навіть якщо він наслідується кілька разів через різні шляхи.

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Note
Примітка

Спробуйте вирішити проблему неоднозначності у попередньому прикладі, використовуючи віртуальне наслідування.

Реалізація ромбовидного наслідування

Для ефективної реалізації ромбовидного наслідування використовуйте ключове слово virtual у визначенні базового класу в проміжних classes. Забезпечте послідовне використання віртуального наслідування на всіх шляхах ієрархії наслідування та звертайте увагу на порядок виклику конструкторів і деструкторів.

Усунення неоднозначностей

Одним із викликів множинного наслідування є також вирішення потенційних неоднозначностей, коли йдеться про члени з однаковими іменами.

main.cpp

main.cpp

copy
12345678910111213141516171819
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

Якщо обидва базові класи мають члени з однаковими іменами, похідний клас може не знати, який саме використовувати. Для вирішення таких неоднозначностей можна скористатися оператором розв'язання області видимості (::), щоб вказати, до якого члена базового класу звертатися. Наприклад:

main.cpp

main.cpp

copy
1234567891011121314151617181920
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.Derived1::display(); obj.Derived2::display(); }
question mark

Яка основна проблема, спричинена ромбовидним успадкуванням?

Select the correct answer

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 4. Розділ 5

Запитати АІ

expand

Запитати АІ

ChatGPT

Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат

course content

Зміст курсу

C++ ООП

C++ ООП

1. Основи ООП у C++
2. Конструктори та Деструктори
3. Огляд Інкапсуляції
4. Огляд Наслідування
5. Огляд Поліморфізму

book
Діамантове Наслідування

Множинне наслідування може призвести до ситуації, відомої як проблема ромба або ромбовидне наслідування, що є суттєвою складністю в мовах об'єктно-орієнтованого програмування, які підтримують множинне наслідування.

Це виникає, коли підклас наслідується від двох або більше classes, які самі наслідуються від спільного базового класу. Термін ромб використовується тому, що схема наслідування нагадує форму ромба.

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};

Основна проблема ромбовидного наслідування — це неоднозначність, яку воно створює. Оскільки Diamond наслідується як від Derived1, так і від Derived2, які, у свою чергу, наслідуються від Base, в об'єкті класу Base існують дві копії Diamond. Це може призвести до неоднозначності.

main.cpp

main.cpp

copy
12345678910111213141516
#include <iostream> class Base { public: void display() { std::cout << "Base display()" << std::endl; } }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

Розв'язання проблеми

Ключове слово virtual допомагає уникнути цієї проблеми. Ви можете вирішити цю неоднозначність за допомогою віртуального наслідування, використовуючи ключове слово virtual. Коли Diamond наслідує віртуально, C++ гарантує, що існує лише одна копія суперкласу, навіть якщо він наслідується кілька разів через різні шляхи.

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Note
Примітка

Спробуйте вирішити проблему неоднозначності у попередньому прикладі, використовуючи віртуальне наслідування.

Реалізація ромбовидного наслідування

Для ефективної реалізації ромбовидного наслідування використовуйте ключове слово virtual у визначенні базового класу в проміжних classes. Забезпечте послідовне використання віртуального наслідування на всіх шляхах ієрархії наслідування та звертайте увагу на порядок виклику конструкторів і деструкторів.

Усунення неоднозначностей

Одним із викликів множинного наслідування є також вирішення потенційних неоднозначностей, коли йдеться про члени з однаковими іменами.

main.cpp

main.cpp

copy
12345678910111213141516171819
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

Якщо обидва базові класи мають члени з однаковими іменами, похідний клас може не знати, який саме використовувати. Для вирішення таких неоднозначностей можна скористатися оператором розв'язання області видимості (::), щоб вказати, до якого члена базового класу звертатися. Наприклад:

main.cpp

main.cpp

copy
1234567891011121314151617181920
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.Derived1::display(); obj.Derived2::display(); }
question mark

Яка основна проблема, спричинена ромбовидним успадкуванням?

Select the correct answer

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 4. Розділ 5
some-alt