Menu
Coddy logo textTech

Kopya Yapıcı

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

Kopya oluşturucu, mevcut bir nesnenin kopyası olarak yeni bir nesne oluşturur. Bir nesneyi aynı türdeki başka bir nesneden başlattığınızda, bir nesneyi değere göre geçirdiğinizde veya bir nesneyi değere göre döndürdüğünüzde çağrılır.

Kopya oluşturucu, aynı sınıftaki bir nesneye const referans alır:

class Player {
    std::string name;
    int health;
public:
    Player(std::string n, int h) : name(n), health(h) {}
    
    // Kopya yapıcı
    Player(const Player& other) {
        name = other.name;
        health = other.health;
    }
};

Player original("Hero", 100);
Player copy = original;    // Kopya yapıcı çağrıldı
Player another(original);  // Ayrıca kopya yapıcıyı çağırır

Bir kopya oluşturucu tanımlamazsanız, derleyici sığ kopyalama işlemi gerçekleştiren bir kopya oluşturucu üretir - her üyenin değerini doğrudan kopyalar. Bu, basit türler için sorunsuz çalışır, ancak sınıfınız dinamik belleği yönettiğinde sorunlara yol açar.

class Buffer {
    int* data;
    size_t size;
public:
    Buffer(size_t s) : size(s) {
        data = new int[size];
    }
    
    // Derin kopya kurucusu
    Buffer(const Buffer& other) : size(other.size) {
        data = new int[size];              // Yeni bellek ayır
        for (size_t i = 0; i < size; i++)
            data[i] = other.data[i];       // İçerikleri kopyala
    }
    
    ~Buffer() { delete[] data; }
};

Özel bir kopya oluşturucu olmadan, her iki nesne de aynı belleği gösterirdi. Biri yok edildiğinde, diğerinde geçersiz bir işaretçi kalırdı. Derin kopya yeni bellek ayırır ve gerçek verileri kopyalar; böylece her nesnenin kendi kaynaklarına sahip olması sağlanır.

challenge icon

Görev

Kolay

Sınıfınız dinamik belleği yönettiğinde derin kopyalamanın önemini gösteren bir mesaj geçmişi sistemi oluşturalım. Mesajları dinamik olarak ayrılmış bir dizide depolayan bir MessageLog sınıfı oluşturacak ve her kopyanın kendine ait bağımsız belleğe sahip olmasını sağlamak için uygun bir kopya oluşturucu uygulayacaksınız.

Kodunuzu düzenlemek için iki dosya oluşturacaksınız:

  • MessageLog.h: Dinamik bellek kullanarak bir mesaj koleksiyonunu yöneten bir MessageLog sınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:
    • Özel üyeler: mesajları depolamak için bir string dizisine işaretçi, maksimum mesaj sayısı için bir capacity ve mevcut mesaj sayısı için bir count
    • Bir kapasite alan, diziyi heap üzerinde ayıran ve count değerini 0 olarak başlatan parametreli oluşturucu
    • Yeni bellek ayırıp kaynak nesnedeki tüm mesajları kopyalayan bir derin kopya gerçekleştiren kopya oluşturucu
    • Ayrılan belleği serbest bırakan ve "MessageLog destroyed" yazdıran bir yıkıcı
    • Yer varsa bir mesaj ekleyen addMessage(string msg) yöntemi
    • Mevcut mesaj sayısını döndüren bir getCount() yöntemi
    • Belirtilen dizindeki mesajı döndüren bir getMessage(int index) yöntemi
  • main.cpp: Kopya oluşturucunuzun bağımsız bir kopya oluşturduğunu gösterin. Girdiden bir kapasite değeri ve iki mesaj okuyun, ardından:
    • Girdi kapasitesiyle MessageLog adlı bir original oluşturun
    • Her iki mesajı da original nesnesine ekleyin
    • Kopya oluşturucuyu kullanarak backup adlı bir kopya oluşturun
    • Yalnızca "New message" nesnesine üçüncü bir mesaj olan original ekleyin
    • "Original count: <count>" yazdırın
    • "Backup count: <count>" yazdırın
    • backup içindeki tüm mesajları satır başına bir tane olacak şekilde yazdırın

Girdi biçimi şöyle olacaktır:

  • İlk satır: kapasite (tam sayı)
  • İkinci satır: ilk mesaj (string)
  • Üçüncü satır: ikinci mesaj (string)

Derin kopyanız doğru şekilde uygulanırsa, yedek 2 mesaja, original ise 3 mesaja sahip olmalıdır: bu, bağımsız belleğe sahip olduklarını kanıtlar. Uygun bir kopya oluşturucu olmadan her ikisi de aynı diziyi paylaşır ve birindeki değişiklikler diğerini etkiler!

Başlık dosyanızı #include "MessageLog.h" kullanarak main.cpp dosyasına dahil edin.

Kendin dene

#include <iostream>
#include <string>
#include "MessageLog.h"
using namespace std;

int main() {
    // Girişi oku
    int capacity;
    cin >> capacity;
    cin.ignore();
    
    string msg1, msg2;
    getline(cin, msg1);
    getline(cin, msg2);

    // TODO: Giriş kapasitesiyle 'original' adında bir MessageLog oluştur

    // TODO: Her iki mesajı da original'e ekle

    // TODO: Kopya yapıcıyı kullanarak 'backup' adında bir kopya oluştur

    // TODO: Yalnızca original'e "New message" ekle

    // TODO: Print "Original count: <count>"

    // TODO: "Backup count: <count>" yazdır

    // TODO: backup'taki tüm mesajları, her satıra bir tane olacak şekilde yazdır

    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