Tembok private yang kita bangun sejak Chapter Access Specifiers memang menjaga data, tetapi kadang ada pihak luar yang justru perlu melihat isi tembok itu: fungsi utilitas yang membandingkan dua object, pemeriksa internal, atau operator << yang ingin mencetak object ke stream. C++ menjawabnya dengan friend — deklarasi di dalam class yang memberi satu fungsi atau satu class izin khusus mengakses member private. friend adalah pengecualian yang sengaja dirancang: kuat, terdokumentasi langsung di class yang diizinkannya, dan harus dipakai hemat.
Apa itu friend #
Deklarasi friend ditulis di dalam badan class dengan kata kunci friend, diikuti prototipe fungsi atau deklarasi class yang diberi izin. Izin ini satu arah: class yang mendeklarasikan memberi akses; pihak yang diberi izin tidak otomatis membalas, dan tidak ada izin yang diwariskan ke class lain. Karena dituliskan eksplisit di dalam class, siapa pun yang membaca definisi class bisa melihat daftar lengkap “tamu istimewa”-nya.
Satu hal yang sering membingungkan pemula: friend bukan member. Deklarasi friend tidak membuat fungsi tersebut menjadi bagian dari class — ia tetap free function biasa di luar class, dipanggil tanpa object (bukan rekening.cetakMutasi(), melainkan cetakMutasi(rekening)). Konsekuensi menariknya: posisi deklarasi friend di dalam class tidak terpengaruh bagian private: atau public: yang sedang aktif. Banyak programmer menaruhnya di bagian atas class justru karena keanehan itu — deklarasi friend tidak mengubah akses siapa pun; ia hanya menyatakan izin.
Friend Function: Fungsi Biasa dengan Akses Khusus #
Friend function adalah free function yang boleh membaca dan menulis member private dari class yang mendeklarasikannya. Tanpa status friend, fungsi tersebut hanya bisa berinteraksi lewat antarmuka public — dan sering kali itu memang cukup. friend function baru masuk akal ketika fungsinya membutuhkan akses ke data internal dari lebih dari satu object sekaligus, atau ketika bentuk pemanggilannya memang harus di luar class.
Kasus paling terkenal di ekosistem C++ adalah overload operator << untuk mencetak object ke std::cout: operator itu ditulis sebagai free function dengan bentuk std::ostream& operator<<(std::ostream&, const NamaClass&), sehingga kalau ia perlu membaca member private, class-nya menjadikannya friend. Pola yang sama dipakai untuk operator perbandingan antar dua object dan untuk helper pengujian yang memeriksa state internal. Kita belum membahas overload operator di course ini, jadi contoh nanti memakai fungsi biasa — strukturnya persis sama.
Friend Class: Membuka Seluruh private #
Deklarasi friend class Nama; memberi seluruh member function dari class tersebut akses penuh ke member private — bukan satu fungsi, melainkan semuanya, termasuk member yang baru ditambahkan di masa depan. Pola ini cocok untuk pasangan class yang memang satu kesatuan desain: class Pabrik yang membangun object dengan state tertentu, class iterator yang berpasangan dengan container-nya, atau class auditor yang menelaah isi class lain.
Harga izin seluas ini harus dihitung. Friend class mempererat ikatan antar dua class: perubahan di member private yang satu langsung berpotensi mematahkan yang lain, dan kebebasan merombak internal — keuntungan utama encapsulation — menyusut untuk kedua pihak. Aturan praktisnya: beri friend function untuk kebutuhan titik-ke-titik, dan friend class hanya bila dua class memang dirancang lahir bersama.
Contoh Lengkap: Mutasi dan Audit #
Program berikut memakai keduanya: cetakMutasi() sebagai friend function dan Auditor sebagai friend class, keduanya diberi izin membaca saldo dan pemilik yang disembunyikan:
#include <iostream>
#include <string>
class RekeningBank {
private:
std::string pemilik;
long long saldo;
// friend BUKAN member: posisinya bebas, tidak terpengaruh
// private/public yang sedang aktif
friend void cetakMutasi(const RekeningBank& rekening);
friend class Auditor;
public:
RekeningBank(const std::string& nama, long long saldoAwal)
: pemilik(nama), saldo(saldoAwal) {}
void setor(long long jumlah) {
saldo += jumlah;
}
};
// Friend function: fungsi bebas (bukan member) yang boleh membaca private
void cetakMutasi(const RekeningBank& rekening) {
std::cout << "Mutasi " << rekening.pemilik
<< ": Rp" << rekening.saldo << "\n";
}
// Friend class: SEMUA member function-nya boleh mengakses private
// RekeningBank, termasuk data member dan method yang belum ditulis
class Auditor {
public:
void periksa(const RekeningBank& rekening) {
std::cout << "Audit " << rekening.pemilik
<< ": saldo tercatat Rp" << rekening.saldo << "\n";
}
};
int main() {
RekeningBank rekening("Budi", 400000);
rekening.setor(100000);
cetakMutasi(rekening); // dipanggil seperti fungsi biasa, bukan rekening.cetakMutasi()
Auditor auditor;
auditor.periksa(rekening);
return 0;
}Output yang Dihasilkan:
Mutasi Budi: Rp500000
Audit Budi: saldo tercatat Rp500000Bedah baris demi baris:
- Baris 5-6 (
std::string pemilik; long long saldo;): data member tetap di section private — friend tidak mengubah status akses member apa pun, hanya menambah daftar pihak yang diizinkan. - Baris 10-12 (deklarasi friend): dua izin diberikan sekaligus, ditulis di dalam section private. Meski demikian, posisinya bisa di mana saja; compiler tidak mengaitkan friend dengan section yang aktif.
- Baris 24-28 (
void cetakMutasi(...)): definisi friend function di luar class. Perhatikan ia mengaksesrekening.pemilikdanrekening.saldosecara langsung — baris ini hanya lolos karena fungsi terdaftar sebagai friend di baris 11. - Baris 32-39 (
class Auditor): friend class dengan satu method. Methodperiksa()membaca member private yang sama; bila nantiAuditormenambah lima method lagi, kelimanya otomatis mewarisi izin ini. - Baris 46-50 (pemanggilan):
cetakMutasi(rekening)dipanggil seperti fungsi biasa — bukti bahwa friend bukan member — sementaraauditor.periksa(rekening)dipanggil lewat objectAuditor-nya sendiri.
Bila deklarasi friend di baris 10-12 kita hapus, kedua fungsi gagal dikompilasi dengan error is private within this context yang sudah kita kenal dari Chapter Access Specifiers. friend benar-benar satu-satunya pintu resmi menembus tembok itu.
Kapan friend Tepat, Kapan Berbahaya #
Gunakan friend ketika salah satu dari ini berlaku: fungsinya secara alami berada di luar class (operator <<, operator pembanding dua object), fungsinya perlu menyentuh internal dua class sekaligus, atau helper pengujian harus memverifikasi state internal tanpa membuka anggota itu ke publik. friend lebih baik daripada dua alternatif yang buruk: menambah getter untuk semua member agar fungsi luar bisa membacanya, atau membuat member jadi public begitu saja.
Bahayanya muncul saat friend dipakai sebagai jalan pintas. Setiap deklarasi friend mempersempit kepemilikan internal class: class tersebut kini tidak lagi bebas mengubah member private-nya sendiri tanpa mempertimbangkan pihak yang diberi izin. Sepuluh friend class berarti sepuluh dependensi tersembunyi, dan refactor yang tadinya lokal menjadi lintas class. Jika daftar friend Anda bertambah terus, itu sinyal desain — kemungkinan besar ada class yang tugasnya seharusnya dipecah, atau fungsi tersebut seharusnya menjadi member function sungguhan.
Dengan friend, kotak peralatan dasar OOP kita lengkap: class, object, access control, constructor, destructor, this, const, static, dan kini pintu khusus untuk pihak terpercaya. Chapter berikutnya merangkai semuanya menjadi prinsip yang menyatukan alat-alat itu: encapsulation, seni menyembunyikan detail dan mengekspos maksud.
Rujukan resmi: friend declaration (cppreference) , Classes (cppreference) .