Warisan berganda dalam C++ sangat kuat, tetapi alat yang rumit, yang sering menyebabkan masalah jika tidak digunakan dengan hati-hati—masalah seperti Masalah Berlian.
Pada artikel ini, kita akan membahas Masalah Berlian, bagaimana hal itu muncul dari pewarisan berganda, dan apa yang dapat Anda lakukan untuk mengatasi masalah tersebut.
Beberapa Warisan dalam C++
Warisan Berganda adalah fitur Pemrograman Berorientasi Objek (OOP) di mana subclass dapat mewarisi lebih dari satu superclass. Dengan kata lain, kelas anak dapat memiliki lebih dari satu orang tua.
Gambar di bawah menunjukkan representasi bergambar dari pewarisan berganda.
Dalam diagram di atas, kelas C memiliki kelas A dan kelas B sebagai orang tuanya.
Jika kita mempertimbangkan skenario kehidupan nyata, seorang anak mewarisi dari ayah dan ibunya. Jadi Anak dapat direpresentasikan sebagai kelas turunan dengan "Ayah" dan "Ibu" sebagai orang tuanya. Demikian pula, kita dapat memiliki banyak contoh kehidupan nyata dari pewarisan berganda.
Dalam pewarisan berganda, konstruktor dari kelas yang diwarisi dieksekusi sesuai urutan pewarisannya. Di sisi lain, destruktor dieksekusi dalam urutan terbalik dari warisan mereka.
Sekarang mari kita ilustrasikan pewarisan berganda dan verifikasi urutan konstruksi dan penghancuran objek.
Ilustrasi Kode Warisan Berganda
Untuk ilustrasi pewarisan berganda, kita telah memprogram representasi di atas dengan tepat dalam C++. Kode untuk program diberikan di bawah ini.
#termasuk
menggunakan namespace std;
kelas A //kelas dasar A dengan konstruktor dan destruktor
{
publik:
A() { cout << "kelas A:: Konstruktor" << endl; }
~A() { cout << "kelas A:: Penghancur" << endl; }
};
kelas B //kelas dasar B dengan konstruktor dan destruktor
{
publik:
B() { cout << "kelas B:: Konstruktor" << endl; }
~B() { cout << "kelas B:: Penghancur" << endl; }
};
kelas C: publik B, publik A //kelas turunan C mewarisi kelas A dan kemudian kelas B (perhatikan urutannya)
{
publik:
C() { cout << "kelas C:: Konstruktor" << endl; }
~C() { cout << "kelas C:: Penghancur" << endl; }
};
int utama(){
Cc;
kembali 0;
}
Output yang kita peroleh dari program di atas adalah sebagai berikut:
kelas B:: Konstruktor
kelas A:: Konstruktor
kelas C:: Konstruktor
kelas C:: Penghancur
kelas A:: Penghancur
kelas B:: Penghancur
Sekarang jika kita memeriksa output, kita melihat bahwa konstruktor dipanggil dalam urutan B, A, dan C sedangkan destruktor berada dalam urutan terbalik. Sekarang setelah kita mengetahui dasar-dasar pewarisan berganda, kita beralih ke pembahasan Masalah Berlian.
Masalah Berlian, Dijelaskan
Masalah Berlian terjadi ketika kelas anak mewarisi dari dua kelas induk yang keduanya berbagi kelas kakek-nenek yang sama. Hal ini digambarkan dalam diagram di bawah ini:
Di sini, kami memiliki kelas Anak mewarisi dari kelas Ayah dan Ibu. Kedua kelas ini, pada gilirannya, mewarisi kelas Orang karena baik Ayah maupun Ibu adalah Pribadi.
Seperti yang ditunjukkan pada gambar, kelas Anak mewarisi sifat-sifat kelas Orang dua kali—sekali dari Ayah dan sekali lagi dari Ibu. Ini menimbulkan ambiguitas karena kompiler gagal memahami ke mana harus pergi.
Skenario ini memunculkan grafik pewarisan berbentuk berlian dan terkenal disebut "Masalah Berlian."
Ilustrasi Kode Masalah Berlian
Di bawah ini kami telah mewakili contoh pewarisan berbentuk berlian di atas secara terprogram. Kode diberikan di bawah ini:
#termasuk
menggunakan namespace std;
kelas Orang { //kelas Orang
publik:
Orang (int x) { cout << "Orang:: Orang (int) dipanggil" << endl; }
};
class Ayah: Orang publik { //class Ayah mewarisi Orang
publik:
Ayah (int x):Orang (x) {
cout << "Ayah:: Ayah (int) dipanggil" << endl;
}
};
class Mother: public Person { //class Mother mewarisi Person
publik:
Ibu (int x):Orang (x) {
cout << "Ibu:: Ibu (int) dipanggil" << endl;
}
};
class Anak: Ayah publik, Ibu publik { //Anak mewarisi Ayah dan Ibu
publik:
Anak (int x): Ibu (x), Ayah (x) {
cout << "Anak:: Anak (int) dipanggil" << endl;
}
};
int utama() {
Anak anak (30);
}
Berikut adalah output dari program ini:
Orang:: Orang (int) dipanggil
Ayah:: Ayah (int) dipanggil
Orang:: Orang (int) dipanggil
Ibu:: Ibu (int) dipanggil
Anak:: Anak (int) disebut
Sekarang Anda dapat melihat ambiguitas di sini. Konstruktor kelas Person dipanggil dua kali: sekali ketika objek kelas Ayah dibuat dan berikutnya ketika objek kelas Ibu dibuat. Properti dari kelas Person diwarisi dua kali, sehingga menimbulkan ambiguitas.
Karena konstruktor kelas Person dipanggil dua kali, destruktor juga akan dipanggil dua kali ketika objek kelas Anak dirusak.
Nah jika sudah memahami masalah dengan benar, mari kita bahas solusi Masalah Berlian.
Cara Memperbaiki Masalah Berlian di C++
Solusi untuk masalah berlian adalah dengan menggunakan Maya kata kunci. Kami membuat dua kelas induk (yang mewarisi dari kelas kakek-nenek yang sama) menjadi kelas virtual untuk menghindari dua salinan kelas kakek-nenek di kelas anak.
Mari kita ubah ilustrasi di atas dan periksa hasilnya:
Ilustrasi Kode untuk Memperbaiki Masalah Berlian
#termasuk
menggunakan namespace std;
kelas Orang { //kelas Orang
publik:
Orang() { cout << "Orang:: Orang() dipanggil" << endl; } //Konstruktor dasar
Orang (int x) { cout << "Orang:: Orang (int) dipanggil" << endl; }
};
class Ayah: Orang publik virtual { //class Ayah mewarisi Orang
publik:
Ayah (int x):Orang (x) {
cout << "Ayah:: Ayah (int) dipanggil" << endl;
}
};
class Mother: virtual public Person { //class Mother mewarisi Person
publik:
Ibu (int x):Orang (x) {
cout << "Ibu:: Ibu (int) dipanggil" << endl;
}
};
class Anak: publik Ayah, publik Ibu { //class Anak mewarisi Ayah dan Ibu
publik:
Anak (int x): Ibu (x), Ayah (x) {
cout << "Anak:: Anak (int) dipanggil" << endl;
}
};
int utama() {
Anak anak (30);
}
Di sini kami telah menggunakan Maya kata kunci ketika kelas Ayah dan Ibu mewarisi kelas Person. Ini biasanya disebut "warisan virtual", yang menjamin bahwa hanya satu turunan dari kelas yang diwarisi (dalam hal ini, kelas Person) yang diteruskan.
Dengan kata lain, kelas Anak akan memiliki satu turunan dari kelas Person, yang digunakan bersama oleh kelas Ayah dan Ibu. Dengan memiliki satu instance dari kelas Person, ambiguitas teratasi.
Output dari kode di atas diberikan di bawah ini:
Orang:: Orang() dipanggil
Ayah:: Ayah (int) dipanggil
Ibu:: Ibu (int) dipanggil
Anak:: Anak (int) disebut
Di sini Anda dapat melihat bahwa konstruktor Person kelas dipanggil hanya sekali.
Satu hal yang perlu diperhatikan tentang pewarisan virtual adalah bahwa meskipun konstruktor berparameter dari Kelas orang secara eksplisit dipanggil oleh konstruktor kelas Ayah dan Ibu melalui inisialisasi daftar, hanya konstruktor dasar dari kelas Person yang akan dipanggil.
Ini karena hanya ada satu instance dari kelas dasar virtual yang digunakan bersama oleh beberapa kelas yang mewarisinya.
Untuk mencegah konstruktor dasar berjalan beberapa kali, konstruktor untuk kelas dasar virtual tidak dipanggil oleh kelas yang mewarisinya. Sebaliknya, konstruktor dipanggil oleh konstruktor kelas beton.
Pada contoh di atas, kelas Anak secara langsung memanggil konstruktor dasar untuk kelas Person.
Terkait: Panduan Pemula untuk Perpustakaan Template Standar di C++
Bagaimana jika Anda perlu menjalankan konstruktor berparameter dari kelas dasar? Anda dapat melakukannya dengan memanggilnya secara eksplisit di kelas Anak daripada kelas Ayah atau Ibu.
Masalah Berlian di C++, Terpecahkan
Masalah Berlian adalah ambiguitas yang muncul dalam pewarisan berganda ketika dua kelas induk mewarisi dari kelas kakek-nenek yang sama, dan kedua kelas induk diwarisi oleh satu kelas anak. Tanpa menggunakan warisan virtual, kelas anak akan mewarisi properti kelas kakek-nenek dua kali, yang mengarah ke ambiguitas.
Ini dapat sering muncul dalam kode dunia nyata, jadi penting untuk mengatasi ambiguitas itu setiap kali terlihat.
Masalah Berlian diperbaiki menggunakan pewarisan virtual, di mana Maya kata kunci digunakan ketika kelas induk mewarisi dari kelas kakek-nenek bersama. Dengan demikian, hanya satu salinan kelas kakek-nenek yang dibuat, dan konstruksi objek kelas kakek-nenek dilakukan oleh kelas anak.
Ingin belajar pemrograman tetapi tidak tahu harus mulai dari mana? Proyek dan tutorial pemrograman pemula ini akan membantu Anda.
Baca Selanjutnya
- Pemrograman
- Pemrograman C
Berlangganan newsletter kami
Bergabunglah dengan buletin kami untuk kiat teknologi, ulasan, ebook gratis, dan penawaran eksklusif!
Klik di sini untuk berlangganan