Topik ini membahas member function secara lebih dalam, yaitu fungsi yang dideklarasikan di dalam kelas dan dipanggil melalui objek. Materinya mencakup parameter objek tersembunyi di balik setiap pemanggilan, kata kunci this, member function const untuk objek yang tidak boleh diubah, serta kata kunci mutable untuk member yang boleh berubah di dalam member function const. Setelah membacanya, pembaca dapat menulis member function dengan kontrak perubahan yang jelas.
Member function dan parameter objek tersembunyi#
Member function selalu dijalankan atas nama satu objek tertentu, dan objek itu ikut tersedia di dalam fungsinya tanpa perlu dikirim sebagai argumen. Pernyataan p.bacaX() pada kelas Titik secara efektif seperti memanggil fungsi biasa dengan p sebagai parameter tambahan. Parameter tersembunyi ini disebut implicit object parameter, dan nama this adalah cara kode di dalam member function merujuknya.
// tidak-dijalankan (ilustrasi cara compiler melihat pemanggilan member function)
p.bacaX();
Titik::bacaX(&p);Kedua baris di atas memiliki makna yang sama bagi compiler, yaitu member function bacaX dijalankan dengan alamat objek p sebagai argumen tambahan yang diterimanya tanpa ditulis. Di dalam badan member function, setiap penyebutan member seperti x membaca member dari objek yang dirujuk oleh parameter tersembunyi itu. Karena alasan inilah member function tidak dapat dipanggil tanpa objek. Pemanggilan Titik::bacaX() tanpa objek ditolak compiler, kecuali fungsinya bertipe member function static yang dibahas pada topik member static.
Kesadaran tentang parameter tersembunyi ini juga menjelaskan mengapa member function dapat membaca member private kelasnya secara bebas. Akses itu diberikan karena fungsi tersebut memang bagian dari kelas, sedangkan objek yang diprosesnya diserahkan melalui parameter tersembunyi pada saat pemanggilan.
Keyword this dan pengembalian *this#
Kata kunci this adalah pointer yang menyimpan alamat objek yang sedang diproses oleh member function, sehingga this->x dan x merujuk member yang sama. Pada umumnya kata ini tidak perlu ditulis, tetapi this menjadi penting ketika member function perlu mengembalikan objeknya sendiri agar pemanggilan dapat dirantai. Kelas berikut memanfaatkannya untuk method geser yang dapat dipanggil berturut-turut.
#include <iostream>
class Titik {
private:
double x = 0.0;
double y = 0.0;
public:
Titik& geser(double dx, double dy) {
x += dx;
y += dy;
return *this;
}
double bacaX() const {
return x;
}
double bacaY() const {
return y;
}
};
int main() {
Titik p;
p.geser(2.0, 1.0).geser(0.5, 3.5).geser(-1.0, 0.0);
std::cout << "p.x = " << p.bacaX() << ", p.y = " << p.bacaY() << "\n";
return 0;
}p.x = 1.5, p.y = 4.5Tipe kembalian Titik& adalah referensi ke objek itu sendiri, sedangkan pernyataan return *this menguraikan pointer this menjadi objek yang dirujuknya. Hasil kembaliannya kemudian menjadi objek tempat panggilan geser berikutnya dilakukan, sehingga tiga pemanggilan itu terjadi pada satu objek p yang sama. Pola ini disebut method chaining dan dipakai luas pada pustaka C++ untuk kode yang membangun objek langkah demi langkah.
Member function const#
Member function const adalah member function yang menjanjikan tidak mengubah member dari objek yang memanggilnya. Janji itu ditulis dengan akhiran const setelah daftar parameter, dan bagi compiler akhiran ini berarti parameter tersembunyinya berupa pointer ke objek const. Member function semacam ini satu-satunya yang dapat dipanggil melalui objek const, sehingga penandaannya wajib untuk fungsi pembaca nilai.
#include <iostream>
class Kotak {
private:
double panjang = 10.0;
double lebar = 4.0;
public:
double luas() const {
return panjang * lebar;
}
void skala(double faktor) {
panjang *= faktor;
lebar *= faktor;
}
};
void cetakInfo(const Kotak& k) {
std::cout << "Luas kotak = " << k.luas() << "\n";
}
int main() {
const Kotak tetap;
std::cout << "Luas tetap = " << tetap.luas() << "\n";
cetakInfo(tetap);
return 0;
}Luas tetap = 40
Luas kotak = 40Objek tetap dinyatakan const, sehingga hanya member function const yang dapat dipanggilnya. Fungsi cetakInfo menerima objek sebagai const Kotak&, yaitu konvensi pengiriman yang menghindari penyalinan tanpa memberi kesempatan perubahan. Fungsi yang menerima parameter const Kotak& hanya dapat memanggil luas, bukan skala, dan pemeriksaannya dilakukan compiler pada waktu kompilasi.
// tidak-dijalankan (member function non-const tidak boleh dipanggil melalui objek const, sehingga kompilasi gagal)
const Kotak tetap;
tetap.skala(2.0);Keyword mutable untuk data sementara#
Kata kunci mutable menghapuskan janji const untuk satu member tertentu, sehingga member itu boleh diubah bahkan dari dalam member function const. Member yang diperlakukan demikian biasanya bukan bagian dari keadaan logis objek, melainkan detail internal seperti cache hasil perhitungan atau penghitung pemakaian. Kelas berikut menghitung jumlah kata dari teks yang tetap, dan menghitung berapa kali perhitungan itu dijalankan.
#include <iostream>
#include <string>
class PenghitungKata {
private:
std::string teks;
mutable int jumlahHitung = 0;
public:
PenghitungKata(const std::string& t) {
teks = t;
}
int hitungKata() const {
++jumlahHitung;
int jumlah = 1;
for (char c : teks) {
if (c == ' ') {
++jumlah;
}
}
return jumlah;
}
int berapaKaliDihitung() const {
return jumlahHitung;
}
};
int main() {
const PenghitungKata kalimat("kucing mengejar bola di taman");
std::cout << "Jumlah kata = " << kalimat.hitungKata() << "\n";
std::cout << "Jumlah kata = " << kalimat.hitungKata() << "\n";
std::cout << "Metode dipanggil = " << kalimat.berapaKaliDihitung() << " kali\n";
return 0;
}Jumlah kata = 5
Jumlah kata = 5
Metode dipanggil = 2 kaliObjek kalimat bersifat const, tetapi setiap pemanggilan hitungKata tetap menaikkan jumlahHitung karena member itu dinyatakan mutable. Perubahan seperti ini tidak dianggap mengubah keadaan logis objek, yaitu teks yang dihitungnya. Pada penerapan nyata, member mutable lazim dipakai untuk menyimpan hasil perhitungan yang mahal, kemudian pemanggilan berikutnya mengembalikan cache tersebut tanpa menghitung ulang.
Kesalahan umum#
Kesalahan berikut paling sering muncul saat menulis member function.
- Lupa menandai fungsi pembaca dengan
const. Akibatnya objekconstdan parameterconst&tidak dapat memanggil fungsinya, dan errornya muncul pada pemanggil, bukan pada definisi fungsinya. - Mengembalikan
Titikbiasa pada pola chaining alih-alihTitik&. Nilai kembalian berupa salinan membuat rantai pemanggilan mengubah salinan yang langsung dibuang, sedangkan objek aslinya tidak berubah. - Memakai
mutableuntuk menghindari kesulitanconst. Keputusan itu menyembunyikan perubahan dari pembaca kode, sehingga lebih baik meninjau ulang kontrak fungsinya.
Ringkasan#
- Setiap member function menerima parameter tersembunyi berupa alamat objek pemanggilnya, dan
thisadalah namanya di dalam kode. return *thismengembalikan objek pemanggil itu sendiri, sehingga member function dapat dirantai dalam satu pernyataan.- Akhiran
constpada member function menjanjikan member tidak diubah, dan hanya member function itu yang dapat dipanggil melalui objekconst. - Kata kunci
mutablememberi pengecualian bagi member internal seperti cache atau penghitung agar tetap boleh berubah di dalam member functionconst.
Referensi#
- Member functions — cppreference
— Aturan member function, akhiran
const, dan ref-qualifier-nya. - this — cppreference
— Arti kata kunci
thisbeserta tipenya. - cv (const dan volatile) — cppreference
— Penjelasan
const,mutable, dan penghapusannya. - The hidden this pointer and member function chaining — LearnCpp
— Penjabaran parameter tersembunyi dan pola pengembalian
*this. - Const class objects and const member functions — LearnCpp
— Aturan objek
constdan member functionconst.