Menu
CoddyTech

Konstruktor Salin

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

copy constructor membuat object baru sebagai salinan dari object yang sudah ada. Copy constructor dipanggil saat kamu menginisialisasi object dari object lain dengan tipe yang sama, meneruskan object berdasarkan nilai, atau mengembalikan object berdasarkan nilai.

Konstruktor salinan menerima referensi const ke object dari class yang sama. Argumennya harus berupa referensi: jika other diteruskan berdasarkan nilai, proses itu sendiri memerlukan salinan, sehingga konstruktor salinan akan dipanggil lagi dan lagi tanpa henti. Konstruktor ini menggunakan const karena membuat salinan tidak boleh mengubah object asli:

class Player {
    std::string name;
    int health;
public:
    Player(std::string n, int h) : name(n), health(h) {}
    
    // Konstruktor penyalin
    Player(const Player& other) {
        name = other.name;
        health = other.health;
    }
};

Player original("Hero", 100);
Player copy = original;    // Konstruktor penyalin dipanggil
Player another(original);  // Juga memanggil konstruktor penyalin

Jika kamu tidak mendefinisikan copy constructor, compiler akan membuatnya untuk melakukan shallow copy, yaitu menyalin nilai setiap anggota secara langsung. Cara ini berfungsi dengan baik untuk tipe sederhana, tetapi menimbulkan masalah saat class-mu mengelola memori dinamis.

class Buffer {
    int* data;
    size_t size;
public:
    Buffer(size_t s) : size(s) {
        data = new int[size];
    }
    
    // Konstruktor salinan mendalam
    Buffer(const Buffer& other) : size(other.size) {
        data = new int[size];              // Alokasikan memori baru
        for (size_t i = 0; i < size; i++)
            data[i] = other.data[i];       // Salin isinya
    }
    
    ~Buffer() { delete[] data; }
};

Tanpa copy constructor khusus, kedua object akan menunjuk ke memori yang sama. Ketika salah satunya dihancurkan, object lainnya akan memiliki pointer yang menggantung. Salinan mendalam mengalokasikan memori baru dan menyalin data yang sebenarnya, sehingga setiap object memiliki resource-nya sendiri.

challenge icon

Tantangan

Mudah

Mari kita buat sistem riwayat pesan yang menunjukkan pentingnya penyalinan mendalam saat class-mu mengelola memori dinamis. Kamu akan membuat class MessageLog yang menyimpan pesan dalam array yang dialokasikan secara dinamis, lalu menerapkan konstruktor salin yang tepat agar setiap salinan memiliki memorinya sendiri yang independen.

Kamu akan membuat dua file untuk mengatur kodemu:

  • MessageLog.h: Definisikan class MessageLog yang mengelola kumpulan pesan menggunakan memori dinamis. Class-mu harus memiliki:
    • Anggota private: pointer ke array string untuk menyimpan pesan, capacity untuk jumlah maksimum pesan, dan count untuk jumlah pesan saat ini
    • Konstruktor berparameter yang menerima kapasitas, mengalokasikan array di heap, dan menginisialisasi count menjadi 0
    • Konstruktor salin yang melakukan penyalinan mendalam: mengalokasikan memori baru dan menyalin semua pesan dari object sumber
    • Destruktor yang membebaskan memori yang dialokasikan dan mencetak "MessageLog destroyed"
    • Method addMessage(string msg) yang menambahkan pesan jika masih ada ruang
    • Method getCount() yang mengembalikan jumlah pesan saat ini
    • Method getMessage(int index) yang mengembalikan pesan pada indeks yang diberikan
  • main.cpp: Tunjukkan bahwa konstruktor salinmu membuat salinan yang independen. Baca nilai kapasitas dan dua pesan dari input, lalu:
    • Buat MessageLog bernama original dengan kapasitas input
    • Tambahkan kedua pesan ke original
    • Buat salinan bernama backup menggunakan konstruktor salin
    • Tambahkan pesan ketiga "New message" hanya ke original
    • Cetak "Original count: <count>"
    • Cetak "Backup count: <count>"
    • Cetak semua pesan dari backup, satu pesan per baris

Format inputnya adalah:

  • Baris pertama: kapasitas (integer)
  • Baris kedua: pesan pertama (string)
  • Baris ketiga: pesan kedua (string)

Jika penyalinan mendalammu diterapkan dengan benar, backup akan memiliki 2 pesan, sedangkan original memiliki 3 pesan. Ini membuktikan bahwa keduanya memiliki memori yang independen. Tanpa konstruktor salin yang tepat, keduanya akan berbagi array yang sama dan perubahan pada salah satunya akan memengaruhi yang lain!

Sertakan file header-mu di main.cpp menggunakan #include "MessageLog.h".

Coba sendiri

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

int main() {
    // Baca input
    int capacity;
    cin >> capacity;
    cin.ignore();
    
    string msg1, msg2;
    getline(cin, msg1);
    getline(cin, msg2);

    // TODO: Buat MessageLog bernama 'original' dengan kapasitas dari input

    // TODO: Tambahkan kedua pesan ke original

    // TODO: Buat salinan bernama 'backup' menggunakan konstruktor salin

    // TODO: Tambahkan "New message" hanya ke original

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

    // TODO: Cetak "Backup count: <count>"

    // TODO: Cetak semua pesan dari backup, satu per baris

    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