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 penyalinJika 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.
Tantangan
MudahMari 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 classMessageLogyang mengelola kumpulan pesan menggunakan memori dinamis. Class-mu harus memiliki:- Anggota private: pointer ke array string untuk menyimpan pesan,
capacityuntuk jumlah maksimum pesan, dancountuntuk 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
- Anggota private: pointer ke array string untuk menyimpan pesan,
main.cpp: Tunjukkan bahwa konstruktor salinmu membuat salinan yang independen. Baca nilai kapasitas dan dua pesan dari input, lalu:- Buat
MessageLogbernamaoriginaldengan kapasitas input - Tambahkan kedua pesan ke
original - Buat salinan bernama
backupmenggunakan konstruktor salin - Tambahkan pesan ketiga
"New message"hanya keoriginal - Cetak
"Original count: <count>" - Cetak
"Backup count: <count>" - Cetak semua pesan dari
backup, satu pesan per baris
- Buat
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;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar-Dasar OOP
File EksternalBuild dan Kompilasi C++File Header dan File SourceNamespace dan CakupanPengantar OOP dalam C++class vs objectPointer 'this'method (Fungsi Anggota)Atribut (Anggota Data)Dasar Ctor dan DtorRingkasan: Kalkulator Sederhana4Properti class
Anggota instance vs staticGetter dan setterFungsi anggota constKata kunci mutableMethod dan variabel staticFungsi dan class friendRangkuman, Pengelola Rekening Bank7Pewarisan
Pewarisan DasarTingkat Akses pada PewarisanUrutan Pemanggilan Ctor & DtorPenimpaan methodFungsi Virtual & VTablePewarisan BergandaPewarisan VirtualRangkuman: Hierarki Karyawan2Manajemen Memori
Memori Stack vs HeapPointer dan ReferenceMemori Dinamis (new/delete)Smart Pointer di C++RAII di C++Rangkuman: Pengelola Array Dinamis5Enkapsulasi
Penentu Akses dalam C++Penentu Akses secara MendalamPenyembunyian Informasistruct vs classNested dan Inner classRangkuman, Sistem Catatan Siswa8Polimorfisme
Polimorfisme saat Compile vs RuntimeOverloading FungsiMeninjau Kembali Fungsi VirtualFungsi Virtual MurniKelas AbstrakDesain Interface di C++Casting Dinamis & RTTIRangkuman: Kalkulator Bentuk3Konstruktor & Destruktor
Konstruktor DefaultKonstruktor BerparameterKonstruktor SalinKonstruktor PindahDaftar Inisialisasi KonstruktorKonstruktor DelegasiKupas Tuntas DestruktorAturan Tiga, Lima, dan NolRangkuman: class String6Overloading Operator
Pengantar Overloading OperatorOverloading Operator AritmetikaOverloading Operator PerbandinganOperator StreamOverloading Operator PenugasanOverloading Operator [] dan ()Operator Konversi TipeRingkasan, class Matrix9Template
Template FungsiTemplate classSpesialisasi TemplateTemplate VariadikDasar SFINAE & Type TraitsRangkuman, Container GenerikLatihan sendiri: Compiler C++ online