Menu
CoddyTech

Pewarisan Virtual

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 54 dari 104.

Masalah diamond terjadi ketika sebuah class mewarisi dua class yang memiliki class induk yang sama. Tanpa penanganan khusus, class turunan akan memiliki dua salinan class induk yang sama, sehingga menimbulkan ambiguitas dan pemborosan memori.

class Animal {
public:
    int age;
};

class Mammal : public Animal {};
class Bird : public Animal {};

class Bat : public Mammal, public Bird {};

Bat b;
b.age = 5;  // Error: ambigu, 'age' yang mana?

class Bat berisi dua subobjek Animal yang terpisah: satu melalui Mammal dan satu melalui Bird. Ini membentuk diagram pewarisan berbentuk berlian yang menjadi asal nama masalah ini.

Virtual inheritance mengatasi hal ini dengan memastikan hanya ada satu salinan dari base bersama. Tambahkan kata kunci virtual saat mewarisi dari base bersama:

class Animal {
public:
    int age;
    Animal(int a = 0) : age(a) {}
};

class Mammal : virtual public Animal {
public:
    Mammal(int a = 0) : Animal(a) {}
};

class Bird : virtual public Animal {
public:
    Bird(int a = 0) : Animal(a) {}
};

class Bat : public Mammal, public Bird {
public:
    Bat(int a) : Animal(a), Mammal(a), Bird(a) {}
};

Bat b(5);
b.age = 10;  // Berhasil! Hanya ada satu 'age'

Perhatikan bahwa Bat harus menginisialisasi Animal secara langsung di dalam constructornya. Dengan inheritance virtual, class paling turunan bertanggung jawab untuk membangun base virtual, terlepas dari class perantara.

challenge icon

Tantangan

Mudah

Mari buat sistem manajemen pekerja yang menunjukkan cara pewarisan virtual menyelesaikan masalah diamond. Kamu akan membuat hierarki dengan TeamLead yang mewarisi dari Developer dan Manager, yang keduanya berbagi class dasar Employee.

Kamu akan mengatur kodemu dalam empat file:

  • Employee.h: Definisikan class dasar bersama Employee dengan:
    • std::string name dan int id yang dilindungi
    • Constructor yang menerima kedua nilai dan mencetak: Employee [<name>] hired with ID <id>
    • Method publik getInfo() yang mencetak: Employee: <name> (ID: <id>)
    • Destructor virtual yang mencetak: Employee [<name>] record closed
  • Developer.h: Definisikan class Developer yang menggunakan pewarisan publik virtual dari Employee:
    • Member std::string language yang dilindungi
    • Constructor yang menerima name, id, dan language: meneruskan name dan id ke Employee, menyimpan language, dan mencetak: Developer [<name>] specializes in <language>
    • Method publik code() yang mencetak: <name> is coding in <language>
    • Destructor yang mencetak: Developer [<name>] signed off
  • Manager.h: Definisikan class Manager yang menggunakan pewarisan publik virtual dari Employee:
    • Member int teamSize yang dilindungi
    • Constructor yang menerima name, id, dan ukuran tim: meneruskan name dan id ke Employee, menyimpan ukuran tim, dan mencetak: Manager [<name>] leads a team of <teamSize>
    • Method publik manage() yang mencetak: <name> is managing <teamSize> people
    • Destructor yang mencetak: Manager [<name>] stepped down
  • main.cpp: Baca empat input, masing-masing pada baris terpisah:
    1. Nama (string)
    2. ID karyawan (bilangan bulat)
    3. Bahasa pemrograman (string)
    4. Ukuran tim (bilangan bulat)

    Definisikan class TeamLead yang mewarisi secara publik dari Developer dan Manager:

    • Constructor yang menerima keempat parameter dan harus menginisialisasi Employee (base virtual) secara langsung, lalu Developer dan Manager
    • Constructor harus mencetak: TeamLead [<name>] ready to lead and code!
    • Method showRole() yang memanggil getInfo(), code(), dan manage() dalam urutan tersebut
    • Destructor yang mencetak: TeamLead [<name>] promoted out

    Buat object TeamLead di dalam cakupan blok, panggil showRole(), lalu biarkan object keluar dari cakupan. Setelah blok, cetak: Organization restructured!

Sebagai contoh, dengan input Alice, 101, C++, dan 5:

Employee [Alice] hired with ID 101
Developer [Alice] specializes in C++
Manager [Alice] leads a team of 5
TeamLead [Alice] ready to lead and code!
Employee: Alice (ID: 101)
Alice is coding in C++
Alice is managing 5 people
TeamLead [Alice] promoted out
Manager [Alice] stepped down
Developer [Alice] signed off
Employee [Alice] record closed
Organization restructured!

Perhatikan bahwa hanya ada satu pemanggilan constructor Employee dan satu pemanggilan destructor Employee: pewarisan virtual memastikan hanya ada satu salinan base bersama. TeamLead harus menginisialisasi Employee secara langsung karena dalam pewarisan virtual, class turunan paling akhir bertanggung jawab untuk membangun base virtual.

Coba sendiri

#include <iostream>
#include <string>
#include "Developer.h"
#include "Manager.h"

using namespace std;

// TODO: Definisikan class TeamLead yang mewarisi secara publik dari Developer dan Manager
// Ingat: Dengan pewarisan virtual, TeamLead harus langsung menginisialisasi Employee (class dasar virtual)
class TeamLead : public Developer, public Manager {
public:
    // TODO: Implementasikan konstruktor yang menerima name, id, language, dan teamSize
    // Harus menginisialisasi: Employee terlebih dahulu (class dasar virtual), lalu Developer, kemudian Manager
    // Harus mencetak: TeamLead [<name>] ready to lead and code!
    TeamLead(const std::string& name, int id, const std::string& language, int teamSize)
        : Employee(name, id),
          Developer(name, id, language),
          Manager(name, id, teamSize) {
        // TODO: Cetak pesan konstruktor
    }

    // TODO: Implementasikan method showRole()
    // Harus memanggil getInfo(), code(), dan manage() sesuai urutan tersebut
    void showRole() {
        // TODO: Panggil ketiga method
    }

    // TODO: Implementasikan destruktor
    // Harus mencetak: TeamLead [<name>] promoted out
    ~TeamLead() {
        // TODO: Cetak pesan destruktor
    }
};

int main() {
    // Baca input
    string name;
    int id;
    string language;
    int teamSize;

    getline(cin, name);
    cin >> id;
    cin.ignore();
    getline(cin, language);
    cin >> teamSize;

    // TODO: Buat object TeamLead di dalam cakupan blok
    // Panggil showRole(), lalu biarkan object tersebut keluar dari cakupan
    {
        // TODO: Buat TeamLead dan panggil showRole()
    }

    // Cetak pesan terakhir setelah blok
    cout << "Organization restructured!" << endl;

    return 0;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online