Konstruktor Salin
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 20 dari 104.
Constructor salin membuat object baru sebagai salinan dari object yang sudah ada. Constructor ini dipanggil saat kamu menginisialisasi object dari object lain dengan tipe yang sama, mengirimkan object berdasarkan nilai, atau mengembalikan object berdasarkan nilai.
Konstruktor salinan menerima referensi const ke objek dari class yang sama. Parameter ini harus berupa referensi: meneruskan other berdasarkan nilai akan memerlukan salinan itu sendiri, sehingga konstruktor salinan akan terus dipanggil tanpa henti. Parameter ini bertipe const karena membuat salinan tidak boleh mengubah objek 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 konstruktor salinan, compiler akan membuatnya dan melakukan salinan dangkal: setiap nilai anggota disalin 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 penyalinan 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 konstruktor salin khusus, kedua objek akan menunjuk ke memori yang sama. Saat salah satunya dihancurkan, objek lainnya akan memiliki pointer yang menggantung. Salinan mendalam mengalokasikan memori baru dan menyalin data sebenarnya, sehingga setiap objek memiliki sumber dayanya sendiri.
Tantangan
MudahMari 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 ke 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 dari 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 seharusnya 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 penyalin
// 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