Menu
Coddy logo textTech

Sanal Kalıtım

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 54 / 104.

Elmas problemi, bir sınıf ortak bir temel sınıfı paylaşan iki sınıftan miras aldığında ortaya çıkar. Özel bir işlem uygulanmadığında, türetilmiş sınıf ortak temelin iki kopyasına sahip olur; bu da belirsizliğe ve bellek israfına neden olur.

class Animal {
public:
    int age;
};

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

class Bat : public Mammal, public Bird {};

Bat b;
b.age = 5;  // Hata: belirsiz - hangi 'age'?

Bat sınıfı iki ayrı Animal alt nesnesi içerir: biri Mammal üzerinden, diğeri ise Bird üzerinden. Bu, probleme adını veren elmas biçimli kalıtım diyagramını oluşturur.

Sanal kalıtım, ortak base sınıfın yalnızca bir kopyasının bulunmasını sağlayarak bu sorunu çözer. Paylaşılan base sınıftan kalıtım alırken virtual anahtar sözcüğünü ekleyin:

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;  // Çalışıyor! Yalnızca bir 'age' var

Bat öğesinin constructor içinde Animal öğesini directly başlatması gerektiğine dikkat edin. virtual inheritance ile en türetilmiş sınıf, ara sınıflardan bağımsız olarak sanal temel sınıfı oluşturmaktan sorumludur.

challenge icon

Görev

Kolay

Elmas problemini sanal kalıtımın nasıl çözdüğünü gösteren bir çalışan yönetim sistemi oluşturalım. TeamLead'in, her ikisi de ortak bir Developer temel sınıfını paylaşan Manager ve Employee sınıflarından kalıtım aldığı bir hiyerarşi oluşturacaksın.

Kodunu dört dosyaya ayıracaksın:

  • Employee.h: Şunlara sahip ortak temel sınıf Employee'ı tanımla:
    • Korumalı bir std::string name ve int id
    • Her iki değeri alan ve şunu yazdıran bir kurucu: Employee [<name>] hired with ID <id>
    • Şunu yazdıran herkese açık bir getInfo() metodu: Employee: <name> (ID: <id>)
    • Şunu yazdıran sanal bir yıkıcı: Employee [<name>] record closed
  • Developer.h: Developer'dan sanal public kalıtım kullanan bir Employee sınıfı tanımla:
    • Korumalı bir std::string language üyesi
    • name, id ve language alan bir kurucu: name ve id değerlerini Employee'a aktarır, language değerini saklar ve şunu yazdırır: Developer [<name>] specializes in <language>
    • Şunu yazdıran herkese açık bir code() metodu: <name> is coding in <language>
    • Şunu yazdıran bir yıkıcı: Developer [<name>] signed off
  • Manager.h: Manager'dan sanal public kalıtım kullanan bir Employee sınıfı tanımla:
    • Korumalı bir int teamSize üyesi
    • name, id ve team size alan bir kurucu: name ve id değerlerini Employee'a aktarır, team size değerini saklar ve şunu yazdırır: Manager [<name>] leads a team of <teamSize>
    • Şunu yazdıran herkese açık bir manage() metodu: <name> is managing <teamSize> people
    • Şunu yazdıran bir yıkıcı: Manager [<name>] stepped down
  • main.cpp: Dört girdi oku (her biri ayrı bir satırda):
    1. Ad (string)
    2. Çalışan kimliği (tam sayı)
    3. Programlama dili (string)
    4. Ekip büyüklüğü (tam sayı)

    Hem TeamLead hem de Developer'dan public olarak kalıtım alan bir Manager sınıfı tanımla:

    • Dört parametrenin tümünü alan ve önce doğrudan Employee'ı (sanal temel sınıf), ardından Developer ve Manager'ı başlatması gereken bir kurucu
    • Kurucu şunu yazdırmalı: TeamLead [<name>] ready to lead and code!
    • showRole(), getInfo() ve code() metotlarını bu sırayla çağıran bir manage() metodu
    • Şunu yazdıran bir yıkıcı: TeamLead [<name>] promoted out

    Bir blok kapsamı içinde bir TeamLead nesnesi oluştur, showRole() metodunu çağır, ardından kapsamından çıkmasına izin ver. Bloktan sonra şunu yazdır: Organization restructured!

Örneğin girdiler Alice, 101, C++ ve 5 olduğunda:

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!

Yalnızca bir Employee kurucu çağrısı ve bir Employee yıkıcı çağrısı olduğuna dikkat et: sanal kalıtım, paylaşılan temel sınıfın yalnızca bir kopyasının bulunmasını sağlar. Sanal kalıtımda sanal temel sınıfı oluşturmak en türetilmiş sınıfın sorumluluğunda olduğundan, TeamLead doğrudan Employee'ı başlatmalıdır.

Kendin dene

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

using namespace std;

// TODO: Hem Developer hem de Manager'dan public olarak miras alan TeamLead sınıfını tanımla
// Unutma: Sanal miras ile TeamLead, Employee'yi (sanal taban) doğrudan başlatmalıdır
class TeamLead : public Developer, public Manager {
public:
    // TODO: name, id, language ve teamSize alan yapıcıyı uygula
    // Başlatılmalı: önce Employee (sanal taban), sonra Developer, sonra Manager
    // Should print: 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: Yapıcı mesajını yazdır
    }

    // TODO: showRole() metodunu uygula
    // getInfo(), code() ve manage() metodlarını bu sırayla çağırmalı
    void showRole() {
        // TODO: Üç metodu çağır
    }

    // TODO: Yıkıcıyı uygula
    // Should print: TeamLead [<name>] promoted out
    ~TeamLead() {
        // TODO: Yıkıcı mesajını yazdır
    }
};

int main() {
    // Girdileri oku
    string name;
    int id;
    string language;
    int teamSize;

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

    // TODO: Bir blok kapsamında bir TeamLead nesnesi oluştur
    // showRole()'u çağır, sonra kapsam dışına çıkmasına izin ver
    {
        // TODO: TeamLead oluştur ve showRole()'u çağır
    }

    // Bloğun ardından son mesajı yazdır
    cout << "Organization restructured!" << endl;

    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi