Pada Chapter Parameterized Constructor kita melihat konsekuensi dari overloading constructor: penugasan yang sama ditulis berulang di setiap overload, dan setiap field baru berarti pekerjaan salin-tempel tambahan. Member initializer list merapikan cara penulisannya, tetapi tidak menghapus pengulangannya. Sejak C++11, C++ menyediakan delegating constructor — constructor yang menyerahkan seluruh pekerjaan inisialisasi ke constructor lain dalam class yang sama. Pola ini menghadirkan satu prinsip yang kita sukai: logika pengisian tinggal di satu tempat.
Masalah: Pengisian yang Berulang #
Bayangkan class dengan tiga overload constructor seperti pada contoh pemesanan sebelumnya. Overload dua parameter mengulang penugasan overload satu parameter, dan overload empat parameter mengulang semuanya lagi. Jika nanti kita menambah validasi — misalnya menolak total negatif — validasi itu harus disalin ke semua overload, dan melupakan satu saja menghasilkan perilaku class yang tidak konsisten.
Dampaknya bukan sekadar bertambahnya baris. Duplikasi inisialisasi menyebarkan pengetahuan tentang “bagaimana object yang sah dibentuk” ke banyak tempat, dan setiap tempat adalah peluang divergensi: dua constructor yang mulanya identik bisa berbeda setelah beberapa revisi tanpa ada yang menyadarinya. Delegating constructor menutup celah ini dengan memaksa semua jalur konstruksi melewati satu pintu yang sama.
Delegating Constructor: Satu yang Bekerja, Sisanya Meneruskan #
Bentuknya seperti member initializer list, tetapi satu-satunya item di daftar adalah pemanggilan constructor class sendiri: Sepeda() : Sepeda("Polygon", 2, "gunung") {}. Constructor yang memanggil disebut delegating constructor, sedangkan yang dipanggil disebut target constructor. Delegating constructor hampir selalu punya badan kosong atau berisi pekerjaan tambahan yang spesifik untuk variasinya — semua pengisian data member tetap tanggung jawab target.
Dua aturan praktis menemani pola ini. Pertama, daftar inisialisasi delegating constructor boleh memuat delegasi saja: kita tidak bisa menulis Sepeda() : Sepeda("Polygon", 2, "gunung"), jenis("custom") {} — campuran delegasi dan inisialisasi member ditolak compiler. Kedua, delegasi tidak boleh membentuk lingkaran; constructor yang pada akhirnya mendelegasikan ke dirinya sendiri akan dideteksi compiler, seperti pesan asli berikut:
cycle.cpp:3:13: error: constructor delegates to itself
3 | A() : A() {}
| ^Urutan Eksekusi: Target Dulu, Baru Penerus #
Saat delegating constructor dijalankan, target constructor selesai terlebih dahulu — termasuk seluruh badannya — baru kemudian badan delegating constructor dieksekusi. Pemahaman urutan ini penting bila kedua badan sama-sama berisi logika: tidak ada pekerjaan yang “tertunda” sampai selesai, melainkan dua fase yang jelas. Program berikut membuktikannya dengan jejak cetak, sekaligus memperlihatkan dua delegating constructor yang mengarah ke target yang sama:
#include <iostream>
#include <string>
class Sepeda {
private:
std::string merek;
int jumlahRoda;
std::string jenis;
public:
// Target constructor: satu-satunya tempat pengisian dilakukan
Sepeda(const std::string& m, int roda, const std::string& j)
: merek(m), jumlahRoda(roda), jenis(j) {
std::cout << "target constructor dijalankan\n";
}
// Delegating constructor: menyerahkan pekerjaan ke target
Sepeda() : Sepeda("Polygon", 2, "gunung") {
std::cout << " -> delegating (tanpa argumen) selesai\n";
}
Sepeda(const std::string& m) : Sepeda(m, 2, "lipat") {
std::cout << " -> delegating (satu argumen) selesai\n";
}
void cetak() {
std::cout << merek << " | " << jumlahRoda << " roda | " << jenis << "\n";
}
};
int main() {
Sepeda a; // delegating -> target
Sepeda b("United"); // delegating -> target
a.cetak();
b.cetak();
return 0;
}Output yang Dihasilkan:
target constructor dijalankan
-> delegating (tanpa argumen) selesai
target constructor dijalankan
-> delegating (satu argumen) selesai
Polygon | 2 roda | gunung
United | 2 roda | lipatBedah baris demi baris:
- Baris 11-16 (target
Sepeda(...)dengan tiga parameter): satu-satunya constructor yang menyentuh data member, ditulis dengan member initializer list sesuai materi Chapter sebelumnya. Jejaktarget constructor dijalankantercetak dua kali pada output — satu kali untuk setiap object yang dibuat. - Baris 19-22 (
Sepeda() : Sepeda("Polygon", 2, "gunung")): delegating constructor tanpa parameter. Ia meneruskan pilihan bawaan ke target; jejak target tercetak lebih dulu, baru jejak delegasinya — bukti urutan eksekusi target-dulu. - Baris 24-27 (
Sepeda(const std::string& m) : Sepeda(m, 2, "lipat")): delegating constructor lain yang mengarah ke target yang sama, hanya meneruskan merek dari pemanggil. NilaijumlahRodadanjenisdiserahkan sepenuhnya kepada target. - Baris 37-38 (pembuatan
adanb): dua object, dua jalur delegasi, satu target. Empat baris pertama output adalah urutan konstruksi keduanya; dua baris terakhir memastikan state akhirnya benar.
Perhatikan pola yang muncul: target menjadi satu-satunya definisi “object Sepeda yang sah”, dan delegating constructor hanya menentukan nilai bawaan yang berbeda. Menambah field baru kini hanya menyentuh target — itulah perbaikan duplikasi yang kita janjikan.
Kapan Pola Ini Paling Berharga #
Delegating constructor paling bermanfaat ketika class punya beberapa “cara masuk” yang ujungnya sama: object dibuat dari file, dari string JSON, dari argumen command line, atau dari nilai bawaan — semuanya pada akhirnya harus melewati inisialisasi inti yang sama. Menaruh inisialisasi inti di target membuat validasi terpusat, dan variasi tinggal memetakan inputnya menjadi argumen. Pola serupa juga lazim di class yang mengelola resource, yang akan terasa lebih dekat setelah kita membahas destructor.
Setelah constructor tuntas — dari default, berparameter, initializer list, hingga delegasi — ada satu member function spesial lagi yang belum kita kenal: destructor, yang dijalankan otomatis saat masa hidup object berakhir. Constructor dan destructor berpasangan membentuk pola penting dalam C++ modern yang bernama RAII.
Rujukan resmi: Delegating constructor (cppreference) , Initialization (cppreference) .