Topik ini membahas dua cara mendefinisikan tipe data buatan sendiri di C++, yaitu struct dan class, beserta penanda wilayah akses yang disebut access specifier dan menentukan siapa yang boleh mengakses setiap member. Pembahasan mencakup pemakaian struct untuk mengelompokkan data, pemakaian class untuk menyembunyikan data, perbedaan keduanya, serta pola pikir enkapsulasi yang menjadi dasar modul ini. Setelah membacanya, pembaca dapat memilih bentuk definisi yang tepat untuk setiap tipe yang dirancang.
Struct untuk mengelompokkan data#
struct mengelompokkan beberapa variabel ke dalam satu nama tipe baru, sehingga data yang saling berkaitan dapat dikirim dan disimpan sebagai satu kesatuan. Variabel di dalam struct dinamakan member, yaitu data dan fungsi yang melekat pada tipe tersebut. Simpan kode berikut sebagai berkas titik.cpp.
#include <cmath>
#include <iostream>
struct Titik {
double x = 0.0;
double y = 0.0;
};
double jarak(Titik a, Titik b) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return std::sqrt(dx * dx + dy * dy);
}
int main() {
Titik asal;
Titik p{3.0, 4.0};
std::cout << "p.x = " << p.x << ", p.y = " << p.y << "\n";
std::cout << "Jarak p ke asal = " << jarak(p, asal) << "\n";
return 0;
}p.x = 3, p.y = 4
Jarak p ke asal = 5Perintah berikut mengompilasi berkas itu dan menjalankan hasilnya. Berkas biner ditempatkan di /tmp agar direktori proyek tetap bersih.
# kompilasi titik.cpp menjadi program di folder sementara /tmp
g++ titik.cpp -o /tmp/titik
# jalankan program hasil kompilasi
/tmp/titikp.x = 3, p.y = 4
Jarak p ke asal = 5Bentuk Titik p{3.0, 4.0} mengisi kedua member secara berurutan, sedangkan Titik asal mengambil nilai awal yang ditulis di dalam definisi struct, yaitu 0.0 untuk setiap member. Kedua member dapat dibaca dan diubah dari mana pun karena tidak ada penanda akses yang ditulis, dan seluruh member struct memang secara default bersifat publik. Struktur seperti ini cocok untuk data pasif yang tidak memiliki aturan khusus atas isinya, misalnya titik koordinat, hasil pengukuran, atau baris data sederhana.
Class dan member private#
class mendefinisikan tipe dengan wilayah akses yang dapat diatur, sehingga data internalnya dapat disembunyikan dari pengguna kelas. Wilayah akses ditentukan oleh tiga access specifier, yaitu public yang terbuka untuk semua kode, private yang hanya dapat diakses dari dalam kelas, dan protected yang terbuka bagi kelas itu sendiri beserta kelas turunannya. Kelas berikut membungkus nilai suhu dengan batasan yang dijaga sendiri.
#include <iostream>
class PengaturSuhu {
private:
double suhu = 20.0;
public:
void atur(double nilaiBaru) {
if (nilaiBaru < 16.0) {
nilaiBaru = 16.0;
}
if (nilaiBaru > 30.0) {
nilaiBaru = 30.0;
}
suhu = nilaiBaru;
}
double baca() const {
return suhu;
}
};
int main() {
PengaturSuhu ruangKerja;
std::cout << "Suhu awal : " << ruangKerja.baca() << " derajat\n";
ruangKerja.atur(24.0);
std::cout << "Setelah atur 24 : " << ruangKerja.baca() << " derajat\n";
ruangKerja.atur(50.0);
std::cout << "Setelah atur 50 : " << ruangKerja.baca() << " derajat\n";
ruangKerja.atur(5.0);
std::cout << "Setelah atur 5 : " << ruangKerja.baca() << " derajat\n";
return 0;
}Suhu awal : 20 derajat
Setelah atur 24 : 24 derajat
Setelah atur 50 : 30 derajat
Setelah atur 5 : 16 derajatMember suhu dinyatakan private, sehingga satu-satunya cara mengubahnya adalah melalui method atur yang memangkas nilai di luar rentang 16 sampai 30 derajat. Batasan semacam ini disebut invarian, yaitu kondisi yang harus selalu benar untuk setiap objek yang hidup. Karena penyaringan berada di satu tempat, invarian tidak dapat dilanggar oleh kode luar, seberapa lupa pun pemakai kelasnya.
// tidak-dijalankan (member suhu bersifat private, sehingga compiler menolak baris penugasannya)
PengaturSuhu ruang;
ruang.suhu = 100.0;Bila baris penugasan itu dibiarkan, compiler menghentikan kompilasi dengan pesan error yang menyatakan member suhu bersifat private. Penolakan itu terjadi saat kompilasi, bukan saat program berjalan, sehingga pelanggaran batas akses tertangkap sebelum program sempat dibagikan kepada pengguna.
Perbedaan struct dan class#
Perbedaan struct dan class pada C++ hanya terletak pada wilayah akses default, yaitu wilayah yang berlaku apabila tidak ada access specifier yang ditulis. Tabel berikut merangkum perbedaannya.
| Aspek | struct | class |
|---|---|---|
| Wilayah akses default | public | private |
| Penggunaan lazim | data pasif tanpa aturan isi | tipe dengan invarian yang dijaga |
| Kemampuan lain | sama dengan class | sama dengan struct |
Selain wilayah akses default, keduanya identik. struct pada C++ dapat memiliki member private, fungsi, constructor, dan seluruh kemampuan kelas lainnya, sedangkan class dapat didefinisikan tanpa satu pun member private. Karena itu pilihan antara keduanya merupakan pernyataan niat bagi pembaca kode. Struktur data yang isinya bebas diakses dideklarasikan dengan struct, sedangkan tipe yang mengendalikan akses ke datanya dideklarasikan dengan class.
Pola pikir enkapsulasi#
Enkapsulasi adalah kebiasaan menyembunyikan data di balik antarmuka yang terkontrol, dan access specifier adalah alat bahasanya. Prinsip kerjanya sederhana. Data dinyatakan private, sedangkan operasi yang boleh dilakukan terhadap data itu dinyatakan public. Pengguna kelas tidak perlu mengetahui cara data disimpan, dan perancang kelas bebas mengubah detail penyimpanan tanpa merusak kode penggunanya, sepanjang antarmuka publiknya tetap sama.
Enkapsulasi bukan berarti setiap member private harus disertai sepasang fungsi pembaca dan penulis. Menyediakan akses penuh melalui fungsi semacam itu menghasilkan kelas yang datanya sama terbukanya dengan member public, hanya dengan sintaks yang lebih panjang. Akses diberikan seperlunya, dan penulisan langsung ke data internal sebaiknya melewati fungsi yang menjaga invarian, seperti atur pada kelas sebelumnya.
Ketiga access specifier tetap dipakai bersama ketika kelas mulai diwariskan. Member protected memang tidak terlihat kegunaannya pada kelas tunggal, tetapi akan menjadi wilayah khusus bagi kelas turunan pada bahasan inheritance. Untuk saat ini, kebiasaan yang dianjurkan adalah menempatkan data pada wilayah private dan membuka hanya operasi yang memang diperlukan.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul saat mulai mendefinisikan tipe sendiri.
- Melupakan titik koma penutup setelah kurung kurawal akhir definisi
classataustruct. Pesan error yang muncul biasanya menunjuk ke baris setelahnya, sehingga perlu diingat bahwa definisi tipe diakhiri};. - Mengakses member
privatedari fungsi luar kelas. Compiler menolaknya dengan error is private, dan perbaikannya adalah menambahkan memberpublicyang menjalankan akses tersebut dengan aturan kelas. - Menjadikan seluruh member
publicdemi kepraktisan. Kepraktisan itu menghilangkan invarian, sehingga setiap bagian program harus menebak sendiri nilai yang sah dan yang tidak.
Ringkasan#
structdanclasshanya berbeda pada wilayah akses default, yaitupublicuntuk struct danprivateuntuk class.- Access specifier
public,private, danprotectedmenentukan siapa yang boleh mengakses setiap member. - Member
privatemenyembunyikan data dan memusatkan pemeriksaan aturan pada satu tempat, sehingga invarian objek tetap terjaga. - Data dinyatakan
privatedan hanya operasi yang memang diperlukan yang dinyatakanpublic.
Referensi#
- Class declaration — cppreference — Aturan deklarasi kelas, wilayah akses, dan arti default aksesnya.
- Member access — cppreference
— Rincian perilaku
public,private, danprotectedpada member. - Introduction to classes — LearnCpp — Pengantar kelas dan objek beserta konvensi penempatan wilayah aksesnya.