05 November 2026

, ,

Mengolah File dan Menangani Kesalahan

Materi C++ • File Handling dan Error Handling

Mengolah File dan Menangani Kesalahan

Bagaimana membuat program yang dapat menyimpan data agar tidak hilang ketika program ditutup? Bagaimana pula memastikan program tetap dapat merespons ketika terjadi kesalahan? Pelajari cara membaca, menulis, dan mengelola file serta menangani kesalahan dalam C++.

File Handling ifstream ofstream fstream Error Handling

Bayangkan kita sedang membuat program untuk mengelola nilai murid. Program tersebut dapat menerima nama, nilai tugas, nilai ujian, menghitung rata-rata, dan menentukan apakah seorang murid dinyatakan lulus.

Program berjalan dengan baik. Namun, ada satu masalah: ketika program ditutup, seluruh data yang telah dimasukkan akan hilang.

Mengapa demikian? Karena selama ini kita menyimpan data menggunakan variabel di dalam memori komputer. Ketika program selesai dijalankan, memori yang digunakan oleh program akan dilepaskan. Data yang hanya tersimpan di sana tidak otomatis menjadi dokumen permanen.

Padahal, dalam aplikasi nyata, kita sering membutuhkan data yang dapat digunakan kembali. Misalnya, data murid harus tetap tersedia meskipun aplikasi ditutup dan dibuka kembali keesokan harinya.

Untuk mengatasi masalah tersebut, program dapat menyimpan data ke dalam file. Dengan begitu, informasi tidak hanya berada di memori ketika program berjalan, tetapi juga dapat disimpan pada media penyimpanan komputer.

Namun, proses pengolahan file tidak selalu berjalan sesuai harapan. File yang ingin dibaca mungkin tidak ditemukan, lokasi penyimpanan mungkin tidak tersedia, atau format data yang dibaca mungkin tidak sesuai. Karena itu, kita juga perlu mempelajari bagaimana program mendeteksi dan menangani kesalahan.

Dalam materi ini, kita akan mempelajari kedua kemampuan tersebut secara bertahap.

1. Mengapa Program Membutuhkan File?

Sebelum membahas kode C++, kita perlu memahami terlebih dahulu perbedaan antara data yang disimpan di memori dan data yang disimpan dalam file.

Ketika program dijalankan, variabel digunakan untuk menyimpan informasi yang dibutuhkan selama proses berlangsung. Misalnya, variabel nama menyimpan nama murid dan variabel nilai menyimpan nilai ujian.

Data tersebut dapat digunakan untuk berbagai operasi, tetapi keberadaannya bergantung pada masa hidup variabel dan program. Ketika program selesai, data di memori tidak otomatis tersimpan sebagai dokumen.

Sementara itu, file merupakan kumpulan data yang disimpan pada media penyimpanan, seperti SSD, hard disk, atau flashdisk. File dapat dibuka kembali oleh program lain maupun oleh program yang sama pada waktu berbeda.

Perbedaan penyimpanan data
Penyimpanan sementara Memori Variabel selama program berjalan
→
Penyimpanan permanen File Data dapat dibuka kembali
Program dapat memindahkan data antara memori dan file.

Contohnya, sebuah aplikasi kasir dapat menggunakan variabel untuk menghitung total belanja. Setelah transaksi selesai, informasi transaksi tersebut dapat disimpan ke file agar dapat diperiksa kembali di kemudian hari.

Inti konsep file handling File handling adalah proses mengelola file melalui program, misalnya membuat file, menulis data, membaca isi file, menambahkan data, dan memeriksa apakah operasi file berhasil dilakukan.

Dalam C++, kita dapat melakukan operasi tersebut menggunakan fasilitas yang tersedia di standard library.

2. Mengenal File Stream dalam C++

Untuk mengolah file, C++ menyediakan library bernama fstream.

Library ini menyediakan beberapa jenis stream yang dapat digunakan untuk melakukan operasi file. Kata stream dapat dipahami sebagai aliran data antara program dan sumber atau tujuan data.

Ketika program membaca file, data mengalir dari file menuju program. Sebaliknya, ketika program menulis file, data mengalir dari program menuju file.

Terdapat tiga class utama yang perlu kita kenal:

Class Fungsi Penggunaan
ifstream Membaca data dari file. Input file.
ofstream Menulis data ke file. Output file.
fstream Membaca sekaligus menulis data. Input dan output file.

Untuk menggunakannya, kita perlu menyertakan library fstream di bagian awal program.

Memanggil library fstreamC++
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

Perhatikan bahwa kita tetap menggunakan iostream untuk menampilkan informasi ke layar dan menerima input dari keyboard. Sementara itu, fstream digunakan untuk melakukan operasi file.

Memahami alur file stream

Alur membaca dan menulis file
Menulis Program
→
Disimpan ke File
dan sebaliknya
Membaca dari File
→
Diterima oleh Program

Dengan memahami tiga class tersebut, kita sudah memiliki dasar untuk membuat program yang dapat menyimpan dan mengambil informasi dari file.

Mari kita mulai dengan contoh sederhana. Kita ingin membuat program yang menyimpan sebuah pesan ke dalam file bernama catatan.txt.

Untuk menulis data, kita menggunakan ofstream.

Contoh 1 — Menulis data ke fileC++
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream file("catatan.txt");

    file << "Belajar pemrograman C++" << endl;
    file << "Materi file handling";

    file.close();

    cout << "Data berhasil ditulis.";

    return 0;
}

Jika program berhasil dijalankan, file catatan.txt akan dibuat pada lokasi kerja program. File tersebut berisi:

Isi catatan.txt
Belajar pemrograman C++
Materi file handling

Mari kita pahami bagian penting dari kode tersebut.

1
ofstream file("catatan.txt"); Membuat objek stream bernama file untuk menulis data ke file catatan.txt. Jika file belum tersedia, operasi pembukaan dengan mode default output akan membuatnya.
2
file << "Belajar pemrograman C++"; Mengirimkan teks dari program ke dalam file menggunakan operator <<.
3
file.close(); Menutup file setelah operasi selesai.

Perlu diperhatikan bahwa ketika file dibuka menggunakan ofstream dengan mode default, isi file lama biasanya akan diganti. Jika file belum ada, file baru akan dibuat.

Perhatikan isi file lama Jika file catatan.txt sebelumnya sudah memiliki data, pembukaan dengan mode output default dapat menghapus isi lama dan menggantinya dengan data baru. Jika ingin mempertahankan isi lama, kita perlu menggunakan mode penambahan data yang akan dibahas berikutnya.

Menulis data dari input pengguna

Program akan lebih berguna jika data yang disimpan berasal dari pengguna, bukan hanya teks yang sudah ditentukan di dalam kode.

Misalnya, kita ingin meminta nama dan umur pengguna, lalu menyimpannya ke dalam file.

Contoh 2 — Menyimpan input penggunaC++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    string nama;
    int umur;

    cout << "Masukkan nama: ";
    getline(cin, nama);

    cout << "Masukkan umur: ";
    cin >> umur;

    ofstream file("data.txt");

    file << nama << endl;
    file << umur << endl;

    file.close();

    cout << "Data berhasil disimpan.";

    return 0;
}

Misalnya pengguna memasukkan nama Andi dan umur 17 tahun. Isi file data.txt akan menjadi:

Isi data.txt
Andi
17

Program tersebut sudah dapat menyimpan data ke file. Namun, bagaimana jika kita ingin menggunakan kembali data yang telah disimpan?

Untuk itu, kita perlu mempelajari cara membaca file.

4. Membaca Data dari File

Setelah data disimpan, kita tentu ingin dapat membukanya kembali. Misalnya, program pengelolaan murid harus dapat menampilkan nama dan umur yang sebelumnya sudah tersimpan.

Untuk membaca data, kita menggunakan ifstream.

Perhatikan contoh berikut:

Contoh 3 — Membaca isi fileC++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream file("data.txt");

    string nama;
    int umur;

    getline(file, nama);
    file >> umur;

    cout << "Nama: " << nama << endl;
    cout << "Umur: " << umur << endl;

    file.close();

    return 0;
}

Jika file berisi nama Andi dan umur 17, hasilnya adalah:

Output
Nama: Andi
Umur: 17

Perhatikan dua perintah untuk membaca data:

(- ) getline(file, nama); digunakan untuk membaca satu baris teks dari file.

(- ) file >> umur; digunakan untuk membaca nilai yang dapat diproses sebagai integer.

Perbedaan keduanya mirip dengan penggunaan getline() dan operator >> ketika menerima input dari keyboard.

Membaca seluruh isi file

Contoh sebelumnya membaca dua data dengan jumlah baris yang sudah diketahui. Namun, bagaimana jika isi file terdiri atas banyak baris dan jumlahnya tidak kita ketahui?

Kita dapat menggunakan perulangan untuk membaca file sampai tidak ada data lagi yang dapat dibaca.

Contoh 4 — Membaca file menggunakan whileC++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream file("catatan.txt");

    string baris;

    while (getline(file, baris)) {
        cout << baris << endl;
    }

    file.close();

    return 0;
}

Setiap kali getline() berhasil membaca satu baris, perulangan akan dijalankan. Ketika sudah tidak ada baris yang dapat dibaca, kondisi perulangan menjadi salah dan program berhenti membaca.

Misalnya, file catatan.txt berisi:

Isi catatan.txt
Belajar C++
Mengenal file handling
Membaca data
Menulis data

Program akan menampilkan seluruh baris tersebut secara berurutan.

Mengapa menggunakan while(getline(...))? Pola ini merupakan cara yang umum dan aman untuk membaca file baris demi baris. Kondisi perulangan sekaligus memeriksa apakah proses pembacaan berhasil.
Pendalaman: mengapa tidak menggunakan while(!file.eof())?

Metode while (!file.eof()) sering ditemukan dalam contoh lama, tetapi bukan cara yang tepat untuk mengendalikan proses pembacaan.

Status EOF baru dapat diketahui setelah operasi pembacaan mencoba melewati akhir file. Akibatnya, pola tersebut dapat menyebabkan data terakhir diproses secara keliru atau menghasilkan pengulangan yang tidak diharapkan.

Lebih baik menggunakan kondisi operasi pembacaan secara langsung, seperti:

Pola yang disarankan
while (getline(file, baris)) {
    cout << baris << endl;
}

5. Menambahkan Data Tanpa Menghapus Isi File

Bayangkan kita membuat aplikasi pencatatan transaksi. Setiap kali pengguna memasukkan transaksi baru, data tersebut harus ditambahkan ke catatan yang sudah ada.

Jika kita menggunakan ofstream dengan mode default, isi file lama dapat terhapus. Padahal, kita ingin mempertahankan seluruh transaksi sebelumnya.

Untuk mengatasi masalah tersebut, kita dapat menggunakan mode ios::app.

Mode ini membuat data baru ditambahkan di bagian akhir file.

Contoh 5 — Menambahkan data ke fileC++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    string transaksi;

    cout << "Masukkan transaksi: ";
    getline(cin, transaksi);

    ofstream file("transaksi.txt", ios::app);

    file << transaksi << endl;

    file.close();

    cout << "Transaksi berhasil ditambahkan.";

    return 0;
}

Misalnya, isi awal file adalah:

Isi awal transaksi.txt
Pembelian buku
Pembelian pensil

Kemudian pengguna memasukkan transaksi baru, yaitu Pembelian penghapus.

Setelah program dijalankan, isi file menjadi:

Isi setelah penambahan
Pembelian buku
Pembelian pensil
Pembelian penghapus

Data lama tetap tersimpan, sedangkan data baru ditambahkan di bagian akhir.

Kapan menggunakan ios::app? Gunakan ios::app ketika ingin menambahkan data baru tanpa mengganti isi file yang sudah ada, misalnya untuk catatan transaksi, riwayat aktivitas, atau daftar log.

6. Memahami Mode Pembukaan File

Selain ios::app, C++ menyediakan beberapa mode pembukaan file lainnya. Mode tersebut menentukan bagaimana file akan diperlakukan ketika dibuka.

Mode Fungsi
ios::in Membuka file untuk membaca data.
ios::out Membuka file untuk menulis data. Jika digunakan sendiri, umumnya isi lama akan dipotong.
ios::app Menambahkan data di akhir file. Setiap penulisan diarahkan ke bagian akhir.
ios::ate Membuka file dan memposisikan posisi awal operasi di akhir file. Posisi dapat dipindahkan setelahnya.
ios::trunc Menghapus isi file ketika file dibuka untuk penulisan.
ios::binary Membuka file dalam mode biner, bukan mode teks.

Beberapa mode dapat digabungkan menggunakan operator OR bitwise |.

Contohnya:

Menggabungkan mode fileC++
fstream file("data.txt", ios::in | ios::out);

Kode tersebut membuka file untuk membaca dan menulis. Perlu diingat bahwa jika file belum tersedia, kombinasi tersebut tidak otomatis membuat file baru seperti pembukaan dengan ofstream biasa.

Pendalaman: apa perbedaan ios::app dan ios::ate?

Keduanya berkaitan dengan posisi akhir file, tetapi memiliki perilaku berbeda.

ios::app memastikan setiap operasi penulisan dilakukan di akhir file.

ios::ate hanya menempatkan posisi awal stream di akhir file ketika dibuka. Setelah itu, posisi dapat dipindahkan menggunakan operasi pencarian posisi seperti seekp().

Untuk kebutuhan sederhana menambahkan catatan di akhir file, biasanya kita menggunakan ios::app.

7. Memeriksa Keberhasilan Operasi File

Sampai di sini kita sudah bisa membaca dan menulis file. Namun, ada satu hal yang tidak boleh diabaikan: bagaimana jika file gagal dibuka?

Misalnya, kita ingin membaca file bernama data_murid.txt, tetapi file tersebut belum dibuat. Atau kita ingin menyimpan data ke lokasi yang tidak dapat diakses oleh program.

Jika kita tidak memeriksa keberhasilan operasi file, program dapat berjalan seolah-olah semuanya baik-baik saja, padahal proses pembacaan atau penulisan sebenarnya gagal.

Untuk itu, kita perlu memeriksa status stream.

Menggunakan is_open()

Method is_open() digunakan untuk memeriksa apakah file berhasil dibuka.

Contoh 6 — Memeriksa file berhasil dibukaC++
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream file("data_murid.txt");

    if (file.is_open()) {
        cout << "File berhasil dibuka.";
        file.close();
    } else {
        cout << "File gagal dibuka.";
    }

    return 0;
}

Jika file tersedia dan dapat dibuka, program akan menampilkan pesan bahwa file berhasil dibuka. Jika tidak, program menampilkan pesan kegagalan.

Menggunakan good(), fail(), dan bad()

Selain is_open(), stream menyediakan beberapa fungsi untuk memeriksa kondisi operasi.

Method Keterangan
good() Mengembalikan true jika tidak ada flag kesalahan stream yang aktif.
fail() Mengembalikan true jika operasi gagal, misalnya format data tidak sesuai atau file tidak berhasil dibuka.
bad() Mengembalikan true jika terjadi kesalahan serius pada operasi stream.
eof() Mengembalikan true jika kondisi akhir file telah terdeteksi.

Contoh penggunaannya:

Contoh 7 — Memeriksa status streamC++
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream file("data.txt");

    if (file.fail()) {
        cout << "Terjadi kegagalan membuka file.";
    } else {
        cout << "File berhasil dibuka.";
    }

    file.close();

    return 0;
}

Perlu diketahui bahwa is_open() dan fail() tidak memeriksa hal yang persis sama. is_open() memeriksa apakah stream terhubung dengan file yang terbuka, sedangkan fail() memeriksa apakah flag kegagalan stream aktif.

Kebiasaan yang baik Jangan langsung menganggap operasi file berhasil. Biasakan memeriksa status pembukaan file dan keberhasilan operasi membaca atau menulis sebelum menggunakan hasilnya.

8. Mengenal Error Handling

Sekarang kita beralih ke bagian kedua dari materi ini, yaitu penanganan kesalahan.

Ketika membuat program, kita tidak dapat mengasumsikan bahwa seluruh proses akan selalu berjalan sesuai rencana. Pengguna dapat memasukkan data yang salah, file dapat tidak ditemukan, atau program dapat menerima kondisi yang tidak dapat diproses.

Kesalahan seperti itu perlu ditangani agar program dapat memberikan respons yang tepat.

Proses mendeteksi dan menangani kesalahan disebut error handling.

Mengapa error handling diperlukan?

Bayangkan sebuah program meminta pengguna memasukkan angka untuk membagi suatu nilai.

Jika pengguna memasukkan angka nol sebagai pembagi, operasi pembagian tersebut tidak dapat dilakukan dalam aritmetika bilangan real biasa. Program perlu memeriksa kondisi tersebut sebelum melakukan perhitungan.

Contohnya:

Contoh 8 — Memeriksa kesalahan pembagianC++
#include <iostream>
using namespace std;

int main() {
    double a, b;

    cout << "Masukkan angka pertama: ";
    cin >> a;

    cout << "Masukkan angka kedua: ";
    cin >> b;

    if (b == 0) {
        cout << "Kesalahan: pembagi tidak boleh nol.";
    } else {
        cout << "Hasil: " << a / b;
    }

    return 0;
}

Program tersebut menggunakan percabangan untuk memeriksa kondisi yang tidak diperbolehkan. Jika pembagi bernilai nol, program menampilkan pesan kesalahan dan tidak melakukan pembagian.

Ini merupakan salah satu bentuk penanganan kondisi yang tidak valid.

Apakah semua kesalahan harus menggunakan try-catch?

Tidak. Dalam C++, kita dapat menangani berbagai kondisi menggunakan percabangan, pemeriksaan nilai, status stream, maupun mekanisme exception.

Misalnya, jika kita hanya ingin memeriksa apakah suatu angka lebih besar dari nol, penggunaan if sudah cukup. Namun, untuk kondisi tertentu yang ingin dilaporkan sebagai exception, kita dapat menggunakan mekanisme try, throw, dan catch.

Perbedaan penting Error handling merupakan konsep umum untuk menangani kesalahan. Sementara itu, exception handling adalah salah satu mekanisme yang disediakan C++ untuk melaporkan dan menangani kondisi kesalahan melalui exception.

9. Menggunakan try, throw, dan catch

C++ menyediakan tiga keyword penting untuk mekanisme exception handling, yaitu try, throw, dan catch.

Ketiganya bekerja bersama untuk menangani kondisi tertentu yang dianggap sebagai exception.

try: bagian kode yang diawasi

Keyword try digunakan untuk membungkus bagian kode yang berpotensi menghasilkan exception.

throw: melempar exception

Keyword throw digunakan untuk melempar atau mengirimkan exception ketika suatu kondisi tertentu terjadi.

catch: menangkap exception

Keyword catch digunakan untuk menangkap exception yang dilempar dari blok try, kemudian menjalankan penanganan yang sesuai.

Alur exception handling
try Menjalankan kode
→
throw Melempar exception
→
catch Menangani exception
Jika exception dilempar, alur normal pada blok try dihentikan dan pencarian handler dilakukan.

Contoh penggunaan try, throw, dan catch

Mari kita kembali ke contoh pembagian. Kali ini, kita akan menggunakan exception untuk menangani pembagian dengan nol.

Contoh 9 — Exception handling sederhanaC++
#include <iostream>
#include <stdexcept>
using namespace std;

int main() {
    double a, b;

    cout << "Masukkan angka pertama: ";
    cin >> a;

    cout << "Masukkan angka kedua: ";
    cin >> b;

    try {
        if (b == 0) {
            throw runtime_error(
                "Pembagi tidak boleh nol."
            );
        }

        cout << "Hasil: " << a / b;
    }
    catch (const runtime_error& e) {
        cout << "Kesalahan: " << e.what();
    }

    return 0;
}

Jika pengguna memasukkan angka kedua bernilai nol, program akan menghasilkan pesan:

Output ketika terjadi exception
Masukkan angka pertama: 10
Masukkan angka kedua: 0
Kesalahan: Pembagi tidak boleh nol.

Mari kita uraikan alurnya.

1
Program masuk ke blok try Bagian kode di dalam try mulai dijalankan.
2
Kondisi diperiksa Jika nilai b sama dengan nol, program menjalankan throw.
3
Exception dilempar Perintah throw runtime_error(...) menghentikan alur normal pada blok try dan mencari handler yang sesuai.
4
Blok catch dijalankan Exception bertipe runtime_error ditangkap oleh catch, kemudian pesan kesalahan ditampilkan menggunakan e.what().

Dengan mekanisme tersebut, kita dapat memisahkan kode utama dengan bagian yang bertugas menangani exception.

Mengapa menggunakan const runtime_error& e?

Perhatikan bagian berikut:

Parameter catch
catch (const runtime_error& e) {
    cout << e.what();
}

Parameter e merupakan referensi konstan terhadap exception yang ditangkap. Dengan cara ini, kita dapat membaca informasi exception tanpa membuat salinan objek dan tanpa mengubahnya.

Method what() digunakan untuk mendapatkan pesan penjelasan dari exception.

Pendalaman: apa itu std::exception?

C++ menyediakan class dasar bernama std::exception untuk berbagai jenis exception standar.

Beberapa class exception standar diturunkan dari class tersebut, seperti std::runtime_error dan std::logic_error.

Kita juga dapat menangkap berbagai jenis exception standar menggunakan:

Menangkap exception umum
catch (const exception& e) {
    cout << e.what();
}

Pastikan menggunakan #include <exception> atau header terkait yang mendeklarasikan jenis exception yang digunakan. Untuk contoh runtime_error, gunakan #include <stdexcept>.

Menangani lebih dari satu jenis exception

Sebuah program dapat memiliki lebih dari satu blok catch. Setiap blok dapat menangani jenis exception yang berbeda.

Contoh 10 — Beberapa blok catchC++
#include <iostream>
#include <stdexcept>
using namespace std;

int main() {
    int pilihan = 2;

    try {
        if (pilihan == 1) {
            throw invalid_argument(
                "Pilihan tidak valid."
            );
        }

        if (pilihan == 2) {
            throw runtime_error(
                "Terjadi kesalahan proses."
            );
        }
    }
    catch (const invalid_argument& e) {
        cout << "Input: " << e.what();
    }
    catch (const runtime_error& e) {
        cout << "Proses: " << e.what();
    }

    return 0;
}

Jika nilai pilihan adalah 2, program akan menjalankan blok catch yang menangani runtime_error.

Blok catch diperiksa berdasarkan urutan penulisannya. Karena itu, ketika menangani class exception yang memiliki hubungan pewarisan, handler yang lebih spesifik sebaiknya diletakkan sebelum handler yang lebih umum.

Jangan menggunakan catch untuk menutupi kesalahan Tujuan exception handling bukan sekadar membuat pesan kesalahan menghilang. Program perlu menangani kondisi tersebut dengan benar, memberikan informasi yang relevan, atau menghentikan proses secara aman jika memang diperlukan.

10. Memahami Jenis Kesalahan dalam Program

Tidak semua kesalahan dalam program memiliki penyebab dan cara penanganan yang sama. Secara umum, kita dapat mengenali beberapa jenis kesalahan berikut.

1. Syntax error

Syntax error terjadi ketika penulisan kode tidak mengikuti aturan sintaks bahasa pemrograman.

Contohnya, lupa menambahkan tanda titik koma:

Contoh syntax errorC++
int nilai = 90
cout << nilai;

Pada contoh tersebut, deklarasi variabel tidak diakhiri dengan titik koma. Compiler akan melaporkan kesalahan ketika mencoba menerjemahkan program.

2. Runtime error

Runtime error merupakan kesalahan yang terjadi ketika program sedang dijalankan.

Contohnya, program mencoba membaca file yang tidak tersedia, melakukan operasi yang tidak valid, atau mengakses sumber daya yang gagal diperoleh.

Beberapa runtime error dapat ditangani melalui pemeriksaan kondisi, sedangkan kondisi tertentu dapat dilaporkan menggunakan exception.

3. Logical error

Logical error terjadi ketika program berhasil dikompilasi dan dijalankan, tetapi menghasilkan keluaran yang tidak sesuai dengan tujuan karena kesalahan logika.

Misalnya, kita ingin menghitung rata-rata tiga nilai, tetapi justru membaginya dengan dua.

Contoh logical errorC++
int nilai1 = 80;
int nilai2 = 90;
int nilai3 = 100;

double rataRata =
    (nilai1 + nilai2 + nilai3) / 2.0;

Kode tersebut dapat dikompilasi dan dijalankan. Namun, hasilnya salah karena jumlah nilai dibagi dua, bukan tiga.

Jenis kesalahanTerjadi kapan?Contoh
Syntax errorSaat proses kompilasi.Lupa titik koma atau salah menulis sintaks.
Runtime errorSaat program berjalan.File gagal dibuka atau operasi tidak valid.
Logical errorSaat program menghasilkan hasil yang salah.Rumus perhitungan tidak tepat.

Ketiga jenis kesalahan tersebut membutuhkan pendekatan penanganan yang berbeda. try-catch bukan solusi untuk semua jenis kesalahan. Syntax error harus diperbaiki pada kode sumber, sedangkan logical error membutuhkan pemeriksaan logika program.

11. Membuat Program Pengelolaan Data dengan File

Sekarang kita akan menggabungkan konsep file handling dan pemeriksaan kesalahan dalam satu program sederhana.

Kita akan membuat program yang dapat menyimpan dan membaca catatan nama murid. Program menyediakan dua pilihan utama:

(- ) Menambahkan nama murid ke dalam file.

(- ) Menampilkan seluruh nama murid yang telah tersimpan.

Data akan disimpan dalam file bernama data_murid.txt. Setiap nama ditulis pada baris yang berbeda.

Contoh 11 — Program pencatatan data muridC++
#include <iostream>
#include <fstream>
#include <string>
#include <limits>
using namespace std;

void tambahMurid() {
    string nama;

    cout << "Masukkan nama murid: ";
    getline(cin, nama);

    if (nama.empty()) {
        cout << "Nama tidak boleh kosong.\n";
        return;
    }

    ofstream file(
        "data_murid.txt",
        ios::app
    );

    if (!file.is_open()) {
        cout << "Gagal membuka file.\n";
        return;
    }

    file << nama << endl;

    if (!file) {
        cout << "Gagal menulis data.\n";
        return;
    }

    file.close();

    cout << "Data berhasil disimpan.\n";
}

void tampilkanMurid() {
    ifstream file("data_murid.txt");

    if (!file.is_open()) {
        cout << "File belum tersedia atau gagal dibuka.\n";
        return;
    }

    string nama;
    int nomor = 1;

    cout << "\nDaftar nama murid:\n";

    while (getline(file, nama)) {
        cout << nomor << ". " << nama << endl;
        nomor++;
    }

    if (file.bad()) {
        cout << "Terjadi kesalahan saat membaca file.\n";
    }

    file.close();

    if (nomor == 1) {
        cout << "Belum ada data murid.\n";
    }
}

int main() {
    int pilihan;

    do {
        cout << "\n=== DATA MURID ===\n";
        cout << "1. Tambah murid\n";
        cout << "2. Tampilkan murid\n";
        cout << "3. Keluar\n";
        cout << "Pilihan: ";

        if (!(cin >> pilihan)) {
            cout << "Input harus berupa angka.\n";
            cin.clear();
            cin.ignore(
                numeric_limits<streamsize>::max(),
                '\n'
            );
            continue;
        }

        cin.ignore(
            numeric_limits<streamsize>::max(),
            '\n'
        );

        switch (pilihan) {
            case 1:
                tambahMurid();
                break;

            case 2:
                tampilkanMurid();
                break;

            case 3:
                cout << "Program selesai.\n";
                break;

            default:
                cout << "Pilihan tidak tersedia.\n";
        }

    } while (pilihan != 3);

    return 0;
}

Memahami cara kerja program

Program tersebut menggunakan beberapa fungsi untuk memisahkan tugas-tugasnya.

1
tambahMurid() Menerima nama dari pengguna, memeriksa apakah nama kosong, kemudian menyimpannya ke file menggunakan ofstream dan ios::app.
2
tampilkanMurid() Membuka file menggunakan ifstream, membaca nama satu per satu, kemudian menampilkannya di layar.
3
main() Menampilkan menu dan menerima pilihan pengguna. Perulangan do-while membuat menu tetap tersedia sampai pengguna memilih keluar.

Mengapa menggunakan numeric_limits?

Perhatikan bagian:

Membersihkan sisa input
cin.ignore(
    numeric_limits<streamsize>::max(),
    '\n'
);

Ketika kita menggunakan cin >> pilihan, karakter newline yang dihasilkan ketika pengguna menekan Enter dapat tertinggal di dalam buffer input.

Jika setelah itu kita langsung menggunakan getline(), fungsi tersebut dapat membaca newline yang tertinggal dan menghasilkan string kosong.

Karena itu, kita menggunakan cin.ignore() untuk membuang sisa karakter hingga newline.

Selain itu, ketika input bukan angka, stream cin dapat masuk ke kondisi gagal. Kita menggunakan cin.clear() untuk menghapus status gagal dan cin.ignore() untuk membuang input yang tidak valid.

Catatan tentang program contoh Program ini merupakan contoh pengelolaan file teks sederhana. Program belum dirancang untuk menangani seluruh kemungkinan kegagalan sistem, seperti kerusakan media penyimpanan atau format data yang lebih kompleks. Namun, contoh ini sudah memperkenalkan kebiasaan penting: memeriksa keberhasilan operasi sebelum mengandalkan hasilnya.

Mencoba program secara bertahap

Untuk memahami hasilnya, cobalah menjalankan program dengan urutan berikut:

(- ) Jalankan program untuk pertama kali.

(- ) Pilih menu tambah murid dan masukkan nama Andi.

(- ) Tambahkan nama Budi dan Citra.

(- ) Pilih menu tampilkan murid.

(- ) Tutup program, kemudian jalankan kembali.

(- ) Pilih menu tampilkan murid sekali lagi.

Jika seluruh proses berhasil, nama-nama yang sudah dimasukkan sebelumnya tetap dapat ditampilkan meskipun program telah ditutup dan dijalankan kembali.

Inilah manfaat utama file handling Data tidak hanya digunakan selama program berjalan, tetapi dapat disimpan dan dibaca kembali pada kesempatan berikutnya.

12. Hal yang Perlu Diperhatikan Saat Mengolah File

Dalam program nyata, pengolahan file memerlukan perhatian lebih dari sekadar membuka, membaca, dan menulis. Ada beberapa kebiasaan yang sebaiknya diterapkan.

1. Periksa keberhasilan membuka file

Jangan langsung membaca atau menulis file tanpa memastikan bahwa file berhasil dibuka.

2. Tutup file setelah selesai digunakan

Gunakan close() ketika operasi telah selesai. Selain itu, stream file C++ juga akan ditutup secara otomatis ketika objek stream keluar dari masa hidupnya.

3. Gunakan mode pembukaan yang sesuai

Jika ingin mengganti isi file, gunakan mode output yang sesuai. Jika ingin menambahkan catatan, gunakan ios::app.

4. Periksa data yang dibaca

Jangan menganggap seluruh isi file selalu sesuai dengan format yang diharapkan. File dapat kosong, berubah, atau berisi data yang tidak sesuai.

5. Hindari mengabaikan pesan kesalahan

Ketika terjadi kegagalan, tampilkan informasi yang cukup jelas agar pengguna mengetahui apa yang terjadi dan apa yang dapat dilakukan selanjutnya.

Pendalaman: apakah file harus selalu berupa file teks?

Tidak. C++ juga dapat mengolah file biner menggunakan mode ios::binary.

File teks menyimpan informasi dalam bentuk karakter yang relatif mudah dibaca manusia, misalnya .txt atau .csv.

File biner menyimpan data dalam bentuk representasi byte. Format ini dapat digunakan untuk menyimpan data yang tidak dimaksudkan untuk dibaca langsung sebagai teks.

Pada tahap awal, file teks lebih mudah dipahami dan cukup untuk latihan file handling.

13. Latihan Pemahaman

Setelah mempelajari file handling dan error handling, cobalah mengerjakan latihan berikut.

Latihan 1 — Memahami file handling

Jelaskan perbedaan antara menyimpan data dalam variabel dan menyimpan data dalam file.

(- ) Mengapa data dalam variabel tidak otomatis tersedia setelah program ditutup?

(- ) Apa manfaat menyimpan data dalam file?

Latihan 2 — Mengenal file stream

Jelaskan perbedaan fungsi dari:

(- ) ifstream

(- ) ofstream

(- ) fstream

Berikan masing-masing satu contoh penggunaannya.

Latihan 3 — Memahami mode file

Apa perbedaan antara ios::out, ios::app, dan ios::binary?

Mengapa kita perlu memilih mode pembukaan file yang sesuai dengan kebutuhan program?

Latihan 4 — Memahami exception handling

Jelaskan fungsi dari keyword berikut:

(- ) try

(- ) throw

(- ) catch

Kemudian jelaskan apa yang terjadi ketika sebuah exception dilempar di dalam blok try.

Latihan 5 — Mengidentifikasi jenis kesalahan

Tentukan apakah kondisi berikut termasuk syntax error, runtime error, atau logical error.

(- ) Program lupa menambahkan titik koma.

(- ) Program menghasilkan rata-rata yang salah karena rumusnya keliru.

(- ) Program gagal membuka file yang ingin dibaca.

Tantangan — Membuat program catatan sederhana

Buatlah program C++ yang dapat menyimpan dan membaca catatan kegiatan harian.

Ketentuan program:

(- ) Memiliki menu untuk menambahkan catatan.

(- ) Memiliki menu untuk menampilkan seluruh catatan.

(- ) Setiap catatan disimpan pada baris baru dalam file.

(- ) Data lama tidak boleh terhapus ketika catatan baru ditambahkan.

(- ) Program harus memeriksa apakah file berhasil dibuka.

(- ) Program dapat kembali ke menu utama setelah satu operasi selesai.

Lihat petunjuk pengerjaan

Gunakan beberapa komponen berikut:

(- ) ofstream untuk menyimpan catatan.

(- ) ios::app untuk menambahkan catatan.

(- ) ifstream untuk membaca catatan.

(- ) while (getline(file, catatan)) untuk membaca setiap baris.

(- ) if untuk memeriksa keberhasilan membuka file.

14. Kesimpulan

File handling dan error handling merupakan dua kemampuan penting ketika kita mulai membuat program yang lebih realistis.

File handling memungkinkan program menyimpan dan membaca data dari media penyimpanan sehingga informasi dapat digunakan kembali meskipun program sudah ditutup.

Sementara itu, error handling membantu program mengenali kondisi yang tidak berjalan sesuai harapan dan memberikan respons yang tepat.

Beberapa hal penting yang telah dipelajari:

(- ) File digunakan untuk menyimpan data agar dapat digunakan kembali.

(- ) fstream merupakan library C++ untuk mengolah file.

(- ) ifstream digunakan untuk membaca file.

(- ) ofstream digunakan untuk menulis file.

(- ) fstream dapat digunakan untuk membaca dan menulis file.

(- ) ios::app digunakan untuk menambahkan data di akhir file.

(- ) is_open() dan status stream dapat digunakan untuk memeriksa keberhasilan operasi file.

(- ) Error handling membantu program merespons kondisi yang tidak diharapkan.

(- ) try, throw, dan catch merupakan bagian dari mekanisme exception handling.

(- ) Syntax error, runtime error, dan logical error merupakan jenis kesalahan yang perlu dikenali ketika mengembangkan program.

Dengan memahami materi ini, kita sudah dapat membuat program yang tidak hanya menerima dan mengolah data, tetapi juga menyimpan informasi serta memeriksa kondisi ketika proses tidak berjalan sesuai rencana.

Selanjutnya: Mengembangkan Program dengan Struktur yang Lebih Baik

Setelah memahami fungsi, array, pointer, OOP, file handling, dan error handling, kita sudah memiliki banyak komponen dasar untuk membangun aplikasi C++.

Tahap berikutnya dapat diarahkan pada pengembangan program yang lebih terstruktur, seperti memisahkan kode ke beberapa file, menggunakan header file, memahami namespace, dan mengenal cara kerja library.

Lanjutkan ke materi Mengorganisasi Program C++ dengan Header dan Source File →

Materi ini merupakan bagian dari rangkaian belajar pemrograman C++ dari dasar. Cobalah menjalankan setiap contoh program, mengubah isi file, serta membuat kondisi kesalahan sendiri agar proses membaca, menulis, dan menangani kesalahan semakin mudah dipahami.
Continue reading Mengolah File dan Menangani Kesalahan
, ,

Memahami Pemrograman Berorientasi Objek

Materi C++ • Pemrograman Berorientasi Objek

Memahami Pemrograman Berorientasi Objek

Bagaimana jika sebuah program tidak hanya berisi kumpulan instruksi, tetapi juga dapat menggambarkan benda, karakter, atau sistem yang memiliki data dan perilakunya sendiri? Kenali konsep Object-Oriented Programming (OOP) dan cara menerapkannya dalam C++.

OOP Class Object Attribute Method

Ketika mulai belajar C++, kita biasanya membuat program dengan urutan instruksi. Kita mendeklarasikan variabel, menerima input, melakukan perhitungan, menggunakan percabangan, perulangan, hingga menyusun fungsi untuk membagi pekerjaan program menjadi beberapa bagian.

Cara tersebut sudah cukup untuk membuat berbagai program sederhana. Misalnya, program menghitung luas bangun datar, menentukan kelulusan murid, atau mengolah nilai ujian.

Namun, bayangkan jika kita ingin membuat program yang lebih besar, seperti sistem perpustakaan, aplikasi sekolah, permainan, atau sistem pengelolaan toko. Di dalamnya terdapat banyak hal yang saling berhubungan: murid, buku, guru, transaksi, produk, dan sebagainya.

Setiap hal tersebut memiliki informasi dan perilaku yang berbeda. Sebuah buku memiliki judul dan penulis, sedangkan perilakunya dapat berupa menampilkan informasi atau mengubah status peminjaman. Sebuah murid memiliki nama dan nomor identitas, sedangkan perilakunya dapat berupa menampilkan profil atau menghitung nilai rata-rata.

Jika seluruh data dan fungsi dibuat secara terpisah tanpa pengorganisasian yang baik, program akan semakin sulit dikelola ketika ukurannya bertambah.

Untuk mengatasi masalah tersebut, kita dapat menggunakan pendekatan pemrograman yang disebut Object-Oriented Programming (OOP) atau pemrograman berorientasi objek.

1. Apa Itu Pemrograman Berorientasi Objek?

Pemrograman berorientasi objek adalah pendekatan dalam membuat program dengan mengorganisasikan kode berdasarkan objek. Objek tersebut dapat memiliki data atau informasi, sekaligus fungsi yang menggambarkan tindakan yang dapat dilakukannya.

Untuk memahami konsepnya, mari kita ambil contoh sebuah mobil.

Sebuah mobil memiliki berbagai informasi, seperti merek, warna, tahun produksi, dan kecepatan. Mobil juga dapat melakukan berbagai tindakan, seperti menyalakan mesin, mempercepat kendaraan, mengurangi kecepatan, dan berhenti.

Jika kita menggambarkan mobil sebagai objek dalam program, informasi dan tindakan tersebut dapat dikelompokkan menjadi satu kesatuan.

Ilustrasi objek mobil
Data / informasi Merek Warna Kecepatan
+
Perilaku / tindakan Menyalakan mesin Mempercepat Berhenti
Objek dapat menggabungkan data dan perilaku yang berkaitan.

Dengan pendekatan OOP, kita tidak perlu memisahkan semua informasi mobil dari fungsi-fungsi yang berkaitan dengannya. Kita dapat menyusunnya dalam satu struktur yang disebut class, kemudian membuat objek berdasarkan class tersebut.

Inti konsep OOP OOP mengorganisasikan program berdasarkan objek yang memiliki data dan perilaku. Pendekatan ini membantu membuat kode lebih terstruktur, mudah dikembangkan, dan lebih mudah dikelola ketika program semakin besar.

2. Mengenal Class dan Object

Sebelum menulis kode OOP, kita perlu memahami dua istilah yang menjadi dasar pendekatan ini, yaitu class dan object.

Apa itu class?

Class adalah cetak biru atau rancangan yang digunakan untuk membuat objek. Di dalam class, kita dapat menentukan data apa saja yang dimiliki objek serta tindakan apa saja yang dapat dilakukannya.

Misalnya, kita ingin membuat program yang mengelola data mobil. Sebelum membuat mobil pertama, kita perlu menentukan rancangan mobil yang akan digunakan.

Rancangan tersebut dapat berisi informasi berupa merek, warna, dan kecepatan. Rancangan itu juga dapat menentukan tindakan seperti mempercepat dan menampilkan informasi mobil.

Rancangan inilah yang disebut class.

Apa itu object?

Object adalah hasil pembuatan atau perwujudan dari sebuah class. Jika class merupakan rancangan, maka object adalah sesuatu yang dibuat berdasarkan rancangan tersebut.

Misalnya, kita memiliki class bernama Mobil. Berdasarkan class tersebut, kita dapat membuat beberapa objek:

Satu class dapat menghasilkan banyak object
Class Mobil
↓
Object 1 mobilA Toyota, Merah
Object 2 mobilB Honda, Hitam
Object 3 mobilC Suzuki, Putih
Setiap object dibuat dari class yang sama, tetapi dapat memiliki nilai atribut berbeda.

Ketiga mobil tersebut berasal dari rancangan yang sama. Namun, masing-masing dapat memiliki merek, warna, dan kecepatan yang berbeda.

Analogi sederhana Class dapat diibaratkan sebagai cetakan kue. Cetakan tersebut menentukan bentuk kue yang akan dibuat. Sementara itu, object adalah kue-kue yang dihasilkan dari cetakan tersebut. Bentuk dasarnya sama, tetapi setiap kue dapat memiliki karakteristik berbeda.
Pendalaman: apakah class dan object merupakan hal yang sama?

Tidak. Class merupakan definisi atau rancangan, sedangkan object merupakan entitas yang dibuat berdasarkan definisi tersebut.

Class menentukan struktur dan perilaku yang tersedia. Object memiliki nilai aktual untuk atribut yang ditentukan oleh class.

Dalam C++, object biasanya dibuat sebagai variabel dengan tipe class yang telah didefinisikan.

3. Mengenal Atribut dan Method

Setelah memahami class dan object, kita perlu mengetahui dua bagian penting yang biasanya terdapat di dalam class, yaitu atribut dan method.

Atribut: informasi yang dimiliki object

Atribut adalah variabel yang didefinisikan di dalam class untuk menyimpan data atau karakteristik suatu objek.

Jika kita membuat class Mobil, atributnya dapat berupa:

(- ) merek untuk menyimpan nama merek mobil.

(- ) warna untuk menyimpan warna mobil.

(- ) kecepatan untuk menyimpan kecepatan mobil.

Setiap objek yang dibuat dari class tersebut dapat memiliki nilai atribut masing-masing.

Method: tindakan yang dapat dilakukan object

Method adalah fungsi yang didefinisikan di dalam class. Method digunakan untuk menggambarkan tindakan atau operasi yang dapat dilakukan oleh objek.

Contohnya, class Mobil dapat memiliki method:

(- ) percepat() untuk menambah kecepatan.

(- ) rem() untuk mengurangi kecepatan.

(- ) tampilkanInfo() untuk menampilkan informasi mobil.

Struktur sederhana sebuah class
Class Mobil
Atribut
merek
warna
kecepatan

Method
percepat()
rem()
tampilkanInfo()
Class mengelompokkan atribut dan method yang saling berkaitan.

Dengan demikian, atribut menjelaskan apa yang dimiliki sebuah objek, sedangkan method menjelaskan apa yang dapat dilakukan oleh objek tersebut.

Ingat perbedaannya Atribut adalah data atau karakteristik objek. Method adalah fungsi atau perilaku yang dimiliki objek.

4. Membuat Class Pertama dalam C++

Sekarang kita mulai menerapkan konsep tersebut ke dalam kode C++.

Untuk membuat class, kita menggunakan keyword class, kemudian diikuti nama class dan tanda kurung kurawal.

Bentuk dasarnya adalah:

Struktur dasar classC++
class NamaClass {
    // Atribut
    // Method
};

Perhatikan tanda titik koma setelah kurung kurawal penutup class. Tanda tersebut wajib ditulis pada deklarasi class.

Mari kita buat class sederhana bernama Mobil.

Contoh 1 — Membuat class MobilC++
#include <iostream>
#include <string>
using namespace std;

class Mobil {
public:
    string merek;
    string warna;

    void tampilkanInfo() {
        cout << "Merek: " << merek << endl;
        cout << "Warna: " << warna << endl;
    }
};

int main() {
    return 0;
}

Mari kita uraikan bagian-bagiannya.

1
class Mobil Mendefinisikan sebuah class dengan nama Mobil.
2
string merek; dan string warna; Mendefinisikan dua atribut untuk menyimpan informasi mobil.
3
void tampilkanInfo() Mendefinisikan method untuk menampilkan informasi mobil.
4
public: Menentukan bahwa bagian setelahnya dapat diakses dari luar class. Kita akan membahasnya lebih lanjut pada bagian berikutnya.

Namun, pada contoh tersebut kita baru membuat rancangan class. Belum ada object yang dibuat. Untuk menggunakan class, kita perlu membuat object berdasarkan class tersebut.

Membuat object dari class

Setelah class Mobil tersedia, kita dapat membuat objek di dalam fungsi main().

Contoh 2 — Membuat object MobilC++
#include <iostream>
#include <string>
using namespace std;

class Mobil {
public:
    string merek;
    string warna;

    void tampilkanInfo() {
        cout << "Merek: " << merek << endl;
        cout << "Warna: " << warna << endl;
    }
};

int main() {
    Mobil mobilSaya;

    mobilSaya.merek = "Toyota";
    mobilSaya.warna = "Merah";

    mobilSaya.tampilkanInfo();

    return 0;
}

Hasil program:

Output
Merek: Toyota
Warna: Merah

Perhatikan bagian Mobil mobilSaya;. Baris tersebut membuat object bernama mobilSaya dari class Mobil.

Untuk mengakses atribut dan method, kita menggunakan operator titik atau ..

Contohnya:

(- ) mobilSaya.merek mengakses atribut merek milik object mobilSaya.

(- ) mobilSaya.warna mengakses atribut warna milik object mobilSaya.

(- ) mobilSaya.tampilkanInfo() menjalankan method milik object mobilSaya.

Perhatikan hubungan class dan object Class Mobil menyediakan rancangan. Object mobilSaya dibuat berdasarkan rancangan tersebut, kemudian memiliki nilai atribut dan dapat menjalankan method yang tersedia.

5. Memahami public dan private

Ketika membuat class, kita mungkin tidak ingin semua atribut dan method dapat diakses secara bebas dari luar class.

Misalnya, bayangkan sebuah sistem rekening bank. Pengguna seharusnya dapat melihat saldo dan melakukan transaksi melalui prosedur yang telah ditentukan. Namun, pengguna tidak seharusnya dapat mengubah nilai saldo secara langsung tanpa aturan.

Untuk mengatur akses terhadap anggota class, C++ menyediakan access specifier.

Tiga access specifier yang perlu dikenal adalah:

Access specifierFungsi
public Anggota class dapat diakses dari luar class melalui object, selama tidak ada aturan lain yang membatasinya.
private Anggota class hanya dapat diakses langsung dari dalam anggota class tersebut dan teman yang diberi izin khusus.
protected Anggota dapat diakses dari dalam class dan class turunannya, dengan aturan tertentu.

Menggunakan private

Mari kita kembali ke contoh mobil. Kita akan membuat atribut kecepatan menjadi private, sehingga nilainya tidak dapat diubah secara langsung dari luar class.

Contoh 3 — Menggunakan private dan publicC++
#include <iostream>
using namespace std;

class Mobil {
private:
    int kecepatan = 0;

public:
    void percepat() {
        kecepatan += 10;
    }

    void tampilkanKecepatan() {
        cout << "Kecepatan: "
             << kecepatan << " km/jam" << endl;
    }
};

int main() {
    Mobil mobilSaya;

    mobilSaya.percepat();
    mobilSaya.percepat();

    mobilSaya.tampilkanKecepatan();

    return 0;
}

Hasil program:

Output
Kecepatan: 20 km/jam

Dalam contoh tersebut, atribut kecepatan disimpan sebagai private. Kita tidak dapat mengubahnya secara langsung melalui object dari fungsi main().

Sebaliknya, method percepat() dan tampilkanKecepatan() dibuat sebagai public. Karena itu, keduanya dapat dipanggil dari luar class.

Jika kita mencoba menuliskan:

Contoh yang tidak diperbolehkanC++
Mobil mobilSaya;

mobilSaya.kecepatan = 100;

Compiler akan menolak kode tersebut karena kecepatan merupakan anggota private.

Mengapa data perlu dibatasi? Pembatasan akses membantu menjaga agar data tidak diubah sembarangan. Perubahan dapat dilakukan melalui method yang menyediakan aturan tertentu. Konsep ini merupakan salah satu dasar dari encapsulation atau enkapsulasi.
Pendalaman: apa perbedaan default class dan struct di C++?

Dalam C++, kita dapat membuat tipe data menggunakan class maupun struct. Keduanya dapat memiliki atribut, method, constructor, dan fitur OOP lainnya.

Perbedaan pentingnya adalah akses default. Anggota class secara default bersifat private, sedangkan anggota struct secara default bersifat public.

Contoh:

Perbedaan default akses
class DataA {
    int nilai; // private
};

struct DataB {
    int nilai; // public
};

6. Mengenal Constructor

Ketika membuat object, terkadang kita ingin memberikan nilai awal pada atributnya secara langsung. Kita memang dapat memberikan nilai setelah object dibuat, seperti contoh sebelumnya. Namun, jika atributnya semakin banyak, cara tersebut dapat menjadi kurang praktis.

C++ menyediakan fitur bernama constructor.

Constructor adalah fungsi khusus di dalam class yang dijalankan secara otomatis ketika object dibuat. Constructor biasanya digunakan untuk menginisialisasi atribut atau menyiapkan kondisi awal object.

Constructor memiliki beberapa ciri:

(- ) Namanya sama dengan nama class.

(- ) Tidak memiliki tipe pengembalian, bahkan bukan void.

(- ) Dipanggil secara otomatis ketika object dibuat.

(- ) Dapat memiliki parameter.

Membuat constructor sederhana

Contoh 4 — Constructor pada class MobilC++
#include <iostream>
#include <string>
using namespace std;

class Mobil {
public:
    string merek;
    string warna;

    Mobil() {
        merek = "Belum diketahui";
        warna = "Belum diketahui";
    }

    void tampilkanInfo() {
        cout << "Merek: " << merek << endl;
        cout << "Warna: " << warna << endl;
    }
};

int main() {
    Mobil mobilSaya;

    mobilSaya.tampilkanInfo();

    return 0;
}

Ketika Mobil mobilSaya; dijalankan, constructor Mobil() otomatis dipanggil. Karena itu, atribut merek dan warna langsung mendapatkan nilai awal.

Hasil program:

Output
Merek: Belum diketahui
Warna: Belum diketahui

Constructor dengan parameter

Selain memberikan nilai awal yang sama, kita juga dapat membuat constructor yang menerima parameter. Dengan cara ini, setiap object dapat langsung dibuat dengan nilai atribut yang berbeda.

Contoh 5 — Constructor dengan parameterC++
#include <iostream>
#include <string>
using namespace std;

class Mobil {
public:
    string merek;
    string warna;

    Mobil(string m, string w) {
        merek = m;
        warna = w;
    }

    void tampilkanInfo() {
        cout << "Merek: " << merek << endl;
        cout << "Warna: " << warna << endl;
    }
};

int main() {
    Mobil mobilA("Toyota", "Merah");
    Mobil mobilB("Honda", "Hitam");

    mobilA.tampilkanInfo();
    cout << endl;
    mobilB.tampilkanInfo();

    return 0;
}

Hasil program:

Output
Merek: Toyota
Warna: Merah

Merek: Honda
Warna: Hitam

Perhatikan bahwa kita tidak perlu lagi mengisi atribut satu per satu setelah object dibuat. Nilai dapat langsung diberikan melalui constructor.

Menggunakan member initializer list

Ada cara yang lebih umum digunakan dalam C++ untuk memberikan nilai awal kepada anggota class, yaitu member initializer list.

Contoh 6 — Constructor dengan initializer listC++
class Mobil {
public:
    string merek;
    string warna;

    Mobil(string m, string w)
        : merek(m), warna(w) {
    }
};

Bagian : merek(m), warna(w) merupakan member initializer list. Atribut diinisialisasi sebelum bagian isi constructor dijalankan.

Untuk contoh sederhana, kedua cara mungkin terlihat menghasilkan hal yang sama. Namun, member initializer list penting dalam C++ karena beberapa anggota class, seperti reference dan anggota bertipe const, harus diinisialisasi dengan cara tersebut.

Pendalaman: apa itu default constructor?

Default constructor adalah constructor yang dapat dipanggil tanpa memberikan argumen.

Jika kita tidak mendefinisikan constructor apa pun, compiler dapat menyediakan default constructor secara otomatis dalam kondisi tertentu.

Namun, ketika kita membuat constructor dengan parameter sendiri, compiler tidak otomatis menyediakan default constructor. Jika masih ingin membuat object tanpa argumen, kita perlu mendefinisikannya secara eksplisit.

7. Mengenal Keyword this

Ketika sebuah class memiliki atribut dan parameter method dengan nama yang sama, kita mungkin kesulitan membedakan keduanya.

Misalnya, kita memiliki atribut bernama nama dan constructor juga menerima parameter bernama nama.

Untuk membedakan anggota object dengan parameter tersebut, C++ menyediakan keyword this.

this merupakan pointer yang merujuk pada object yang sedang menjalankan method non-static tersebut.

Contoh 7 — Menggunakan thisC++
#include <iostream>
#include <string>
using namespace std;

class Murid {
private:
    string nama;

public:
    Murid(string nama) {
        this->nama = nama;
    }

    void tampilkanNama() {
        cout << "Nama: " << this->nama;
    }
};

int main() {
    Murid muridA("Andi");

    muridA.tampilkanNama();

    return 0;
}

Hasil program:

Output
Nama: Andi

Perhatikan baris:

Bagian penting
this->nama = nama;

Penjelasannya:

(- ) this->nama merujuk pada atribut nama milik object yang sedang dibuat.

(- ) nama di sebelah kanan merupakan parameter yang diterima constructor.

Dengan demikian, perintah tersebut menyalin nilai parameter ke atribut object.

Catatan sintaks Karena this merupakan pointer, anggota object diakses menggunakan operator panah ->, bukan operator titik ..
Pendalaman: apakah this dapat digunakan di semua method?

this tersedia pada fungsi anggota non-static. Pada fungsi anggota static, tidak ada object tertentu yang sedang menjalankan fungsi tersebut, sehingga this tidak tersedia.

Untuk tahap awal, cukup pahami bahwa this digunakan untuk merujuk pada object yang sedang menjalankan method.

8. Membuat Banyak Object dari Satu Class

Sekarang kita sudah memahami bagaimana membuat class, atribut, method, dan constructor. Selanjutnya, mari kita lihat bagaimana konsep tersebut membantu ketika sebuah program memiliki banyak objek.

Misalnya, kita ingin membuat program sederhana untuk menyimpan data beberapa murid. Setiap murid memiliki nama dan umur, tetapi nilainya berbeda-beda.

Kita dapat membuat satu class bernama Murid, kemudian membuat beberapa object dari class tersebut.

Contoh 8 — Mengelola beberapa objectC++
#include <iostream>
#include <string>
using namespace std;

class Murid {
public:
    string nama;
    int umur;

    Murid(string n, int u) {
        nama = n;
        umur = u;
    }

    void tampilkanInfo() {
        cout << "Nama: " << nama << endl;
        cout << "Umur: " << umur << endl;
    }
};

int main() {
    Murid muridA("Andi", 16);
    Murid muridB("Budi", 17);
    Murid muridC("Citra", 16);

    muridA.tampilkanInfo();
    cout << endl;

    muridB.tampilkanInfo();
    cout << endl;

    muridC.tampilkanInfo();

    return 0;
}

Hasil program:

Output
Nama: Andi
Umur: 16

Nama: Budi
Umur: 17

Nama: Citra
Umur: 16

Perhatikan bahwa kita hanya membuat satu class, tetapi dapat menghasilkan banyak object dengan data yang berbeda.

Setiap object memiliki nilai atributnya sendiri. Mengubah data milik muridA tidak otomatis mengubah data milik muridB atau muridC.

Inilah salah satu manfaat utama OOP: kita dapat membuat struktur yang sama untuk berbagai objek tanpa harus menulis ulang seluruh atribut dan method.

9. OOP Dibandingkan dengan Pemrograman Prosedural

Sebelum mempelajari OOP, kita lebih sering membuat program menggunakan pendekatan prosedural. Pada pendekatan ini, program disusun berdasarkan urutan instruksi dan fungsi-fungsi yang menjalankan tugas tertentu.

Contohnya, sebuah program pengelolaan data murid dapat memiliki variabel untuk menyimpan nama dan umur, kemudian memiliki fungsi untuk menampilkan data tersebut.

Contoh 9 — Pendekatan proseduralC++
#include <iostream>
#include <string>
using namespace std;

string nama = "Andi";
int umur = 16;

void tampilkanInfo() {
    cout << "Nama: " << nama << endl;
    cout << "Umur: " << umur << endl;
}

int main() {
    tampilkanInfo();

    return 0;
}

Pendekatan tersebut dapat berjalan dengan baik untuk contoh sederhana. Namun, ketika jumlah data dan fungsi semakin banyak, pengelolaan variabel global dan fungsi yang saling berkaitan dapat menjadi lebih rumit.

Dengan OOP, kita dapat mengelompokkan data dan fungsi yang berkaitan ke dalam class.

AspekProseduralBerorientasi objek
Fokus utamaUrutan instruksi dan fungsi.Objek yang memiliki data dan perilaku.
PengorganisasianData dan fungsi dapat dikelola secara terpisah.Data dan method dapat dikelompokkan dalam class.
Pengelolaan dataDapat menggunakan variabel dan struktur data.Dapat menggunakan atribut dan aturan akses.
PengembanganDapat menjadi sulit ketika fungsi dan data semakin kompleks jika tidak dirancang dengan baik.Membantu mengorganisasikan sistem kompleks melalui objek dan class.

Perlu dipahami bahwa OOP bukan berarti pendekatan prosedural sudah tidak digunakan. Keduanya merupakan pendekatan pemrograman yang dapat digunakan sesuai kebutuhan. Bahkan dalam program C++, kita dapat menemukan fungsi prosedural sekaligus class dan object dalam satu aplikasi.

10. Contoh Penerapan OOP: Program Data Produk

Agar konsep OOP lebih mudah dipahami, sekarang kita akan membuat contoh yang sedikit lebih nyata.

Bayangkan kita ingin membuat program sederhana untuk mengelola informasi produk di sebuah toko. Setiap produk memiliki nama, harga, dan jumlah stok. Program juga perlu menampilkan informasi produk serta menghitung nilai total stok berdasarkan harga dan jumlah barang.

Kita dapat membuat class Produk yang memiliki atribut dan method sesuai kebutuhan tersebut.

Contoh 10 — Program pengelolaan produkC++
#include <iostream>
#include <string>
using namespace std;

class Produk {
private:
    string nama;
    double harga;
    int stok;

public:
    Produk(string n, double h, int s) {
        nama = n;
        harga = h;
        stok = s;
    }

    void tampilkanInfo() {
        cout << "Nama produk: " << nama << endl;
        cout << "Harga: Rp" << harga << endl;
        cout << "Stok: " << stok << endl;
    }

    double hitungNilaiStok() {
        return harga * stok;
    }

    void tambahStok(int jumlah) {
        if (jumlah > 0) {
            stok += jumlah;
        }
    }
};

int main() {
    Produk produkA("Buku Tulis", 5000, 20);

    produkA.tampilkanInfo();

    cout << "Nilai seluruh stok: Rp"
         << produkA.hitungNilaiStok()
         << endl;

    produkA.tambahStok(5);

    cout << endl;
    cout << "Setelah stok ditambahkan:" << endl;

    produkA.tampilkanInfo();

    return 0;
}

Hasil program:

Output
Nama produk: Buku Tulis
Harga: Rp5000
Stok: 20
Nilai seluruh stok: Rp100000

Setelah stok ditambahkan:
Nama produk: Buku Tulis
Harga: Rp5000
Stok: 25

Mari kita pahami bagaimana class tersebut bekerja.

Atribut sebagai penyimpan informasi

Class Produk memiliki tiga atribut:

(- ) nama untuk menyimpan nama produk.

(- ) harga untuk menyimpan harga produk.

(- ) stok untuk menyimpan jumlah barang yang tersedia.

Ketiga atribut tersebut dibuat sebagai private, sehingga tidak dapat diubah secara langsung dari luar class.

Constructor untuk memberikan nilai awal

Constructor Produk() menerima tiga parameter. Ketika object dibuat, nilai parameter tersebut digunakan untuk mengisi atribut nama, harga, dan stok.

Method untuk menjalankan tindakan

Class tersebut memiliki tiga method:

(- ) tampilkanInfo() untuk menampilkan informasi produk.

(- ) hitungNilaiStok() untuk menghitung nilai seluruh stok.

(- ) tambahStok() untuk menambah jumlah stok jika jumlah yang diberikan lebih dari nol.

Perhatikan bahwa method tambahStok() tidak memberikan akses langsung kepada pengguna untuk mengubah atribut stok. Perubahan dilakukan melalui method yang sudah memiliki pemeriksaan sederhana.

Inilah salah satu manfaat pengorganisasian OOP Informasi produk dan operasi yang berkaitan dengannya berada dalam satu class. Ketika kita ingin mengembangkan program, kita dapat menambahkan method atau aturan baru tanpa harus menyebarkan seluruh logika ke berbagai bagian program.

11. Mengenal Empat Konsep Utama OOP

Sejauh ini kita telah mengenal class, object, atribut, method, access specifier, dan constructor. Semua itu merupakan fondasi awal untuk memahami OOP.

Dalam pembahasan yang lebih mendalam, terdapat empat konsep utama yang sering digunakan untuk menjelaskan pemrograman berorientasi objek, yaitu encapsulation, inheritance, polymorphism, dan abstraction.

Kita akan mengenal gambaran dasarnya terlebih dahulu.

1. Encapsulation (Enkapsulasi)

Encapsulation adalah konsep menggabungkan data dan method yang berkaitan dalam satu kesatuan sekaligus mengatur akses terhadap data tersebut.

Contohnya adalah class Produk sebelumnya. Atribut harga dan stok dibuat private, sedangkan perubahan stok dilakukan melalui method tambahStok().

Dengan demikian, data tidak dapat diubah secara sembarangan dari luar class.

Gambaran sederhana Seperti mesin ATM. Pengguna dapat melakukan transaksi melalui pilihan yang disediakan, tetapi tidak dapat mengakses dan mengubah isi sistem internal ATM secara langsung.

2. Inheritance (Pewarisan)

Inheritance adalah konsep ketika sebuah class dapat mewarisi atribut dan method dari class lain.

Misalnya, kita memiliki class Kendaraan yang memiliki informasi umum seperti merek dan warna. Kemudian, kita membuat class Mobil dan Motor yang mewarisi karakteristik umum tersebut.

Ilustrasi inheritance
Class induk Kendaraan
↓
Class turunan Mobil
Class turunan Motor
Class turunan dapat mewarisi anggota tertentu dari class induk.

Dengan inheritance, kita dapat menggunakan kembali bagian kode yang sudah dibuat sehingga tidak perlu menuliskan ulang semua karakteristik yang sama.

3. Polymorphism (Polimorfisme)

Polymorphism berarti satu antarmuka atau bentuk pemanggilan dapat memiliki perilaku berbeda bergantung pada objek atau tipe yang terlibat.

Misalnya, kita memiliki beberapa jenis kendaraan. Setiap kendaraan memiliki method bunyikanSuara(), tetapi suara yang dihasilkan dapat berbeda.

Mobil dapat menghasilkan suara klakson, sedangkan motor dapat menghasilkan suara klakson yang berbeda. Nama method dapat sama, tetapi implementasinya dapat berbeda melalui mekanisme polymorphism.

4. Abstraction (Abstraksi)

Abstraction adalah konsep menyederhanakan penggunaan suatu sistem dengan menampilkan bagian yang penting dan menyembunyikan detail implementasi yang tidak perlu diketahui oleh pengguna.

Misalnya, ketika kita menggunakan kendaraan, kita cukup mengetahui cara menghidupkan mesin dan mengendalikan kendaraan. Kita tidak harus memahami seluruh proses mekanis yang terjadi di dalam mesin.

Dalam pemrograman, abstraksi membantu pengguna class berinteraksi melalui antarmuka yang jelas tanpa harus mengetahui seluruh detail cara kerja internalnya.

KonsepGagasan utamaContoh sederhana
EncapsulationMenggabungkan data dan method serta mengatur akses.Atribut saldo diakses melalui method transaksi.
InheritanceMewariskan anggota class.Mobil dan motor mewarisi class kendaraan.
PolymorphismSatu antarmuka dapat memiliki perilaku berbeda.Method suara pada jenis kendaraan berbeda.
AbstractionMenyederhanakan penggunaan dengan menyembunyikan detail.Pengguna mengoperasikan kendaraan tanpa memahami seluruh mekanisme mesin.

Empat konsep tersebut akan dibahas lebih mendalam pada materi berikutnya. Untuk saat ini, pastikan kita sudah memahami hubungan antara class, object, atribut, dan method terlebih dahulu.

12. Latihan Pemahaman

Setelah mempelajari konsep OOP, cobalah mengerjakan latihan berikut untuk mengetahui sejauh mana pemahaman kita.

Latihan 1 — Memahami class dan object

Jelaskan perbedaan antara class dan object menggunakan contoh selain mobil.

(- ) Apa yang dimaksud dengan class?

(- ) Apa yang dimaksud dengan object?

(- ) Mengapa satu class dapat menghasilkan banyak object?

Latihan 2 — Mengidentifikasi atribut dan method

Misalnya kita ingin membuat class bernama Buku untuk program perpustakaan.

Tentukan minimal empat atribut dan tiga method yang sesuai untuk class tersebut.

Lihat petunjuk

Pikirkan informasi yang dimiliki buku, seperti judul, penulis, dan tahun terbit. Kemudian pikirkan tindakan yang dapat dilakukan, seperti menampilkan informasi atau mengubah status peminjaman.

Latihan 3 — Memahami access specifier

Apa perbedaan antara public dan private?

Mengapa atribut penting dalam sebuah class sering dibuat sebagai private?

Latihan 4 — Memahami constructor

Perhatikan deklarasi berikut:

Soal
class Produk {
public:
    string nama;
    double harga;

    Produk(string n, double h) {
        nama = n;
        harga = h;
    }
};

(- ) Apa fungsi constructor pada class tersebut?

(- ) Kapan constructor dijalankan?

(- ) Apa fungsi parameter n dan h?

Tantangan — Membuat class DataMurid

Buatlah program C++ dengan class bernama DataMurid.

Ketentuan program:

(- ) Memiliki atribut nama, kelas, dan nilai.

(- ) Menggunakan constructor untuk memberikan nilai awal.

(- ) Memiliki method untuk menampilkan informasi murid.

(- ) Memiliki method untuk menentukan apakah murid dinyatakan lulus atau belum.

(- ) Gunakan batas kelulusan nilai 75.

Lihat kerangka awal program
Kerangka programC++
#include <iostream>
#include <string>
using namespace std;

class DataMurid {
private:
    string nama;
    string kelas;
    double nilai;

public:
    // Buat constructor

    // Buat method tampilkanInfo()

    // Buat method cekKelulusan()
};

int main() {
    // Buat object DataMurid

    // Panggil method yang diperlukan

    return 0;
}

13. Kesimpulan

Pemrograman berorientasi objek memberikan cara lain untuk menyusun program. Jika sebelumnya kita lebih sering mengelompokkan instruksi berdasarkan fungsi, melalui OOP kita dapat mengorganisasikan program berdasarkan objek yang memiliki data dan perilakunya sendiri.

Beberapa hal penting yang telah dipelajari:

(- ) OOP merupakan pendekatan pemrograman yang berorientasi pada objek.

(- ) Class merupakan rancangan untuk membuat objek.

(- ) Object merupakan hasil pembuatan dari sebuah class.

(- ) Atribut digunakan untuk menyimpan data atau karakteristik objek.

(- ) Method merupakan fungsi yang menjadi bagian dari class.

(- ) Access specifier seperti public dan private digunakan untuk mengatur akses terhadap anggota class.

(- ) Constructor digunakan untuk menginisialisasi object ketika dibuat.

(- ) Keyword this merujuk pada object yang sedang menjalankan method non-static.

(- ) Encapsulation, inheritance, polymorphism, dan abstraction merupakan empat konsep utama yang akan dipelajari lebih mendalam.

OOP sangat berguna ketika kita mulai membuat program dengan struktur yang lebih kompleks. Dengan memahami class dan object, kita sudah memiliki dasar untuk mempelajari bagaimana berbagai komponen program dapat bekerja sama secara terorganisasi.

Selanjutnya: Mengenal Encapsulation dalam C++

Kita sudah mengetahui bahwa sebuah class dapat memiliki atribut dan method. Namun, bagaimana cara memastikan data di dalam object tidak diubah secara sembarangan?

Pada materi berikutnya, kita akan membahas encapsulation secara lebih mendalam, mulai dari pembatasan akses menggunakan private, penggunaan getter dan setter, hingga cara menjaga agar data object tetap berada dalam kondisi yang valid.

Lanjutkan ke materi Encapsulation dalam C++ →

Materi ini merupakan bagian dari rangkaian belajar pemrograman C++ dari dasar. Jalankan contoh program menggunakan compiler C++ dan cobalah mengubah nilai atribut maupun method agar hubungan antara class dan object semakin mudah dipahami.
Continue reading Memahami Pemrograman Berorientasi Objek