Kita sudah sering menulis method yang sebenarnya tidak mengubah apa pun: cetak(), hitungLuas(), luas(). Compiler juga tahu itu — asalkan kita mengatakannya. Menambahkan kata kunci const setelah kurung parameter member function adalah janji eksplisit kepada compiler: method ini hanya membaca state object dan tidak akan mengubah member apa pun. Janji kecil ini berdampak besar: compiler mengawalinya, object const baru bisa memakai method tersebut, dan pembaca kode langsung tahu fungsi mana yang aman dipanggil tanpa takut state berubah.

Makna const pada Member Function #

Posisi kata const pada member function adalah setelah kurung parameter: void cetak() const;. Maknanya bisa dibaca lewat kacamata this dari chapter sebelumnya: di dalam method const, tipe this menjadi const NamaClass*, sehingga setiap percobaan menulis ke member — radius *= faktor; atau memanggil method non-const lain — ditolak compiler. const di sini bukan tentang parameter atau nilai kembalian; ia menjadikan seluruh object pemanggil sebagai benda read-only selama method berjalan.

Method const punya satu pembatasan tambahan: di dalamnya, kita hanya boleh memanggil member function lain yang juga const. Logikanya konsisten — method yang berjanji tidak mengubah object tidak boleh mendelegasikan pekerjaannya ke method yang tidak memberi janji sama. Karena itu, saat sebuah class punya method const, seluruh “jalur baca” yang dipanggilnya harus ikut ditandai const.

Object const Hanya Bisa Memanggil Method const #

Manfaat terbesarnya muncul saat object itu sendiri bersifat const — misalnya diterima sebuah fungsi sebagai const Lingkaran& atau dideklarasikan dengan kata kunci const. Object const menolak semua perubahan, dan C++ menegakkannya lewat aturan akses: object const hanya boleh memanggil member function yang const. Bila kita memaksakan method non-const, compiler menolaknya sebelum program jadi, dengan pesan g++ 14.2 seperti berikut:

text
consterr.cpp:11:19: error: passing 'const Lingkaran' as 'this' argument discards qualifiers [-fpermissive]
   11 |     tetap.besarkan(2.0);
      |     ~~~~~~~~~~~~~~^~~~~
consterr.cpp:7:10: note:   in call to 'void Lingkaran::besarkan(double)'

Pesan discards qualifiers sebenarnya memuat cerita yang sudah kita kenal: compiler mencoba meneruskan alamat object const sebagai argumen this, tetapi method besarkan() menuntut this yang boleh menulis — syarat yang tidak bisa dipenuhi object const. Tanpa kata const pada method, seluruh API class menjadi tidak bisa dipakai dari context const; itu penyebab error semacam ini muncul berhari-hari setelah orang menambah object const di bagian lain program.

Kesalahan Umum: Lupa const #

Kesalahan paling lazim adalah menulis method yang memang tidak mengubah apa pun, tetapi lupa menandainya const. Kode terlihat benar, program berjalan — sampai suatu hari method itu dipanggil dari object const atau dari fungsi yang menerima parameter const NamaClass&, dan tiba-tiba kompilasi gagal di baris yang semula tidak bersalah. Kesalahan ini menular juga ke pemanggilan berantai: method pembaca yang dipakai di dalam method const lain wajib const, sehingga satu kelalaian merambat.

Konvensi kerja yang mencegahnya sederhana: setiap kali menulis member function, tanyakan “apakah ia mengubah member?” — bila tidak, tambahkan const di akhir deklarasinya, sejak baris pertama. Menambahkannya belakangan juga sah, tetapi akan memaksa kita menyusuri seluruh pemanggilan internal yang harus ikut const. Compiler adalah sahabat di sini: biarkan ia menandai setiap jalur yang belum memberi janji.

Contoh Lengkap: Dua Object, Dua Aturan #

Program berikut mendefinisikan Lingkaran dengan method const (luas(), cetak()) dan method non-const (besarkan()), lalu memanggil semuanya dari object biasa maupun object const:

cpp
#include <iostream>

class Lingkaran {
private:
    double radius;

public:
    Lingkaran(double r) : radius(r) {}

    // Method const: hanya membaca state, tidak mengubah apa pun
    double luas() const {
        return 3.141592653589793 * radius * radius;
    }

    void cetak() const {
        std::cout << "Lingkaran r=" << radius
                  << ", luas = " << luas() << "\n";
    }

    // Method biasa: boleh mengubah state
    void besarkan(double faktor) {
        radius *= faktor;
    }
};

int main() {
    Lingkaran biasa(2.0);
    biasa.cetak();            // object biasa: boleh memanggil method apa pun

    const Lingkaran tetap(1.0);
    tetap.cetak();            // object const: hanya method const yang boleh
    std::cout << "luas tetap: " << tetap.luas() << "\n";

    biasa.besarkan(1.5);
    biasa.cetak();

    return 0;
}

Output yang Dihasilkan:

text
Lingkaran r=2, luas = 12.5664
Lingkaran r=1, luas = 3.14159
luas tetap: 3.14159
Lingkaran r=3, luas = 28.2743

Bedah baris demi baris:

  1. Baris 10-13 (double luas() const): method perhitungan yang hanya membaca radius, ditandai const. Ia bisa dipanggil dari object mana pun, termasuk yang const.
  2. Baris 15-19 (void cetak() const): method const yang memanggil method const lain (luas()) — pola yang sah karena keduanya memberi janji yang sama. Bila luas() tidak const, baris ini yang akan error.
  3. Baris 22-25 (void besarkan(double faktor)): method non-const yang mengubah radius. Hanya object non-const yang boleh memanggilnya.
  4. Baris 28-33 (object biasa dan tetap): biasa memanggil cetak() lalu besarkan() tanpa keluhan; tetap hanya memanggil cetak() dan luas(). Panggilan tetap.besarkan(2.0) — yang kita tampilkan sebagai error pada bagian sebelumnya — sudah diganti dengan jalur yang sah.
  5. Baris 34-35 (biasa.besarkan(1.5)): membuktikan object non-const tetap bebas: radius naik ke 3.0, dan cetak() terakhir menampilkan luas yang membesar.

Dengan const, kita kini bisa menandai mana method yang hanya membaca. Chapter berikutnya pindah ke kategori member yang berperilaku lain dari yang selama ini kita kenal: static, member yang bukan milik satu object melainkan milik class itu sendiri.

Rujukan resmi: const member functions (cppreference) , this (cppreference) .