Back to IF2010 Pemrograman Berorientasi Objek

Operator Overloading

Questions/Cues

  • Apa itu Operator Overloading?
  • Bagaimana cara deklarasi & implementasi?
  • Kapan pakai member vs. non-member (friend)?
  • Apa saja aturan & batasan overloading?
  • Bagaimana implementasi operator= (Assignment)?
  • Bagaimana implementasi operator[] (Subscript)?
  • Bagaimana implementasi operator<< & operator>> (Stream)?
  • Apa itu “Anggota Kelas Minimal”?

Reference Points

  • Materi PDF: “Bahasa C++: Operator Overloading”
  • Materi PDF: “Bahasa C++: Konsep Kelas (bagian II)”
  • Materi Pendukung: “Tutorial 1”

Konsep Dasar Operator Overloading

Operator Overloading adalah fasilitas di C++ yang memungkinkan kita memberikan makna baru pada simbol operator yang sudah ada (seperti +, -, *, =, <<) untuk digunakan pada tipe data yang kita definisikan sendiri (objek kelas). Tujuannya adalah untuk membuat sintaks manipulasi objek menjadi lebih alami dan intuitif.

// Tanpa overloading, kode bisa jadi kurang intuitif
Complex z = x.add(y.divide(z)); 
 
// Dengan overloading, kode lebih matematis dan mudah dibaca
Complex z = x + y / z; 

Ini pada dasarnya adalah bentuk function overloading, di mana nama fungsinya adalah operator@, dengan @ adalah simbol operator.

Implementasi: Member vs. Non-Member Function

Ada dua cara untuk mendefinisikan fungsi operator:

  1. Sebagai Fungsi Anggota (Member Function)

    • Dideklarasikan di dalam kelas.
    • Operan di sebelah kiri operator secara implisit adalah objek itu sendiri (*this).
    • Jumlah parameter formalnya adalah jumlah operan dikurangi satu.

    C++

    class Complex {
    public:
        Complex operator/(const Complex& other); // Hanya butuh 1 parameter untuk operan kanan
    };
  2. Sebagai Fungsi Non-Anggota (Non-Member Function)

    • Dideklarasikan di luar kelas.
    • Jumlah parameter formalnya sama dengan jumlah operan.
    • Jika perlu mengakses anggota private atau protected dari kelas, fungsi ini harus dideklarasikan sebagai friend di dalam kelas tersebut.
    class Matrix {
        friend Matrix operator*(const Matrix& a, const Matrix& b); // Butuh 2 parameter
    };
     
    // Implementasi non-member
    Matrix operator*(const Matrix& a, const Matrix& b){
        Matrix result; 
        // Logika perkalian matriks di sini. 
        // Fungsi ini bisa mengakses anggota private dari 'a' dan 'b' 
        // karena sudah diberi izin 'friend'. 
        // ... 
        return result;
    }

Kapan Memilih Member vs. Non-Member?

  • Operator =, [], (), dan -> wajib diimplementasikan sebagai fungsi anggota.
  • Jika operan di sebelah kiri bukan merupakan objek dari kelas kita (contoh: std::cout << myObject;), operator tersebut wajib diimplementasikan sebagai fungsi non-anggota (biasanya friend).

Aturan dan Batasan Overloading

  • Tidak bisa mengubah presedensi (urutan prioritas) dan arity (jumlah operan) dari sebuah operator.
  • Tidak bisa membuat simbol operator baru.
  • Operator :: (scope), . (member selector), .*, ?: (ternary), dan sizeof tidak bisa di-overload.
  • Untuk membedakan ++ prefix dan postfix, versi postfix didefinisikan dengan satu parameter int dummy: T& operator++(); (prefix) vs T operator++(int); (postfix).

Studi Kasus: Operator Kunci

  • operator= (Assignment)

    • Berbeda dengan copy constructor. Assignment (a = b;) terjadi pada dua objek yang keduanya sudah ada, sementara copy constructor (Stack s2 = s1;) menciptakan objek baru.

    • Implementasinya harus melakukan deep copy: membebaskan memori lama, mengalokasikan memori baru, lalu menyalin konten.

    • Harus mengembalikan *this by reference (Stack&) untuk mendukung chaining (a = b = c;).

    Stack& Stack::operator=(const Stack& s) {
        delete[] data; // 1. Bebaskan memori lama
        size = s.size;
        data = new int[size]; // 2. Alokasikan memori baru
        topStack = s.topStack;
        for (int i=0; i<topStack; i++) data[i] = s.data[i]; // 3. Salin konten
        return *this; // 4. Kembalikan reference ke objek saat ini
    }
  • operator[] (Subscript)

    • Memungkinkan objek untuk diakses seperti array. Berguna untuk membuat container kustom atau map yang bisa melakukan pengecekan batas indeks.
  • operator<< & operator>> (Stream)

    • Digunakan untuk membuat I/O yang seragam dan intuitif. Biasanya diimplementasikan sebagai fungsi friend non-anggota karena operan kirinya adalah objek stream (std::ostream atau std::istream), bukan objek kelas kita.

Anggota Kelas Minimal (“The Big Four”)

  • Konsep ini menekankan kembali bahwa perancang kelas yang mengelola sumber daya (seperti memori dinamis dengan new) sebaiknya selalu mendefinisikan empat fungsi berikut untuk memastikan perilaku penyalinan dan penghancuran yang benar:
    1. Constructor
    2. Copy Constructor
    3. Operator Assignment (=)
    4. Destructor

Summary

  • Operator Overloading memungkinkan kelas kustom di C++ untuk bekerja dengan operator standar (+, =, <<, dll.), membuat kode lebih intuitif. Implementasi dapat dilakukan sebagai member function (jika operan kiri adalah objek kelas) atau non-member/friend function (untuk fleksibilitas, seperti pada stream I/O).
  • Mendefinisikan operator= dengan benar—melakukan deep copy dan mengembalikan *this by reference—adalah bagian krusial dari “Anggota Kelas Minimal” untuk manajemen sumber daya yang aman dan dapat diprediksi.