PEMROGRAMAN APLIKASI DENGAN C++ | |
1. Dasar-dasar Pemrograman C++ 2. Fungsi dalam C++ 3. Pointer dan Array |
4. Kelas 5. Merancang Aplikasi Berorientasi Obyek |
Konsep kelas pada c++ sama persis dengan apa yang telah kita pahami pada label sebelumnya. Konsep ini diturunkan dari paradigma pemrograman berorientasi obyek yang telah disampaikan pada label tersebut. Apabila kita telah mengerti dengan baik konsep pemrograman berorientasi obyek dan pemrograman kelas pada Java, maka konsep kelas pada c++ bukanlah persoalan yang sulit. Perlu kita ketahui, java mengambil sebagian besar konsep pemrograman c++ (termasuk kelas) untuk diterapkan. Perbedaan utama mungkin hanya pada sintaks penulisannya. Pada label ini, konsep pemrograman berorientasi obyek tidak akan dibahas ulang, namun akan langsung pada penerapannya pada c++.
Deklarasi kelas
Sama seperti pada Java, pembuatan kelas dalam C++ menggunakan kata kunci class. Di dalam kelas tersebut terdapat data dan method yang akan digunakan oleh obyek yang akan dibuat (instance) dari kelas tersebut. Data dan method ini biasanya disebut sebagai anggota kelas (class member). Method dalam C++ sama bentuknya dengan fungsi yang telah kita pahami di sub label sebelumnya. Perhatikan contoh berikut.Contoh 9.26. Deklarasi dan penggunaan kelas.
#include <iostream> using namespace std;
class PersegiPanjang {
int x, y;
public:
void set_nilai (int,int);
int luas() {return (x*y);}
};
void PersegiPanjang::set_nilai (int a, int b) {
x = a;
y = b;
}
int main () {
PersegiPanjang pp1, pp2;
pp1.set_nilai (3,4);
pp2.set_nilai (7,12);
cout << "Luas pp1 : " << pp1.luas()<<endl;
cout << "Luas pp2 : " << pp2.luas()<<endl;
return 0;
}
Pada contoh di atas, kelas yang kita deklarasikan bernama PersegiPanjang dan mempunyai anggota kelas dua data yaitu: x dan y, juga dua method yaitu: set_nilai dan luas(). Dua buah method tersebut ditetapkan mempunyai akses public. Seperti halnya java, ada 3 hak akses terhadap data atau method dalam kelas, yaitu: public, private, dan protected. Public berarti anggota kelas tersebut dapat diakses dari luar kelas. Private berarti anggota kelas tersebut hanya dapat diakses di dalam kelas tersebut. Sedangkan protected berarti anggota kelas tersebut dapat diakses oleh turunan (subclass) dari kelas tersebut, tetapi tidak oleh bagian di luar kelas.
Method set_nilai mempunyai dua argument/parameter yang semuanya bertipe data int namun tidak memiliki pengembalian nilai, sehingga kita menggunakan kata kunci void. Method luas() tidak memiliki argumen, namun memiliki pengembalian nilai. Untuk method yang memiliki pengembalian nilai, maka kita menggunakan tipe data di depan nama method.
Pada C++ kita dapat mengimplementasikan method di dalam kelas atau di luar kelas, tetapi deklarasi method harus berada di dalam kelas. Umumnya kita meletakkan implementasi method di luar kelas (di luar tanda { }). Perhatikan pada contoh di atas. Deklarasi method set_nilai terletak di dalam kelas PersegiPanjang namun implementasinya berada di luar kelas. Sedangkan method luas(), baik deklarasi maupun implementasi berada di dalam kelas. Pada implementasi method di luar kelas kita menggunakan tanda :: untuk mendefinisikan anggota kelas di luar kelasnya (perhatikan pada baris void PersegiPanjang::set_nilai (int a, int b)).
Setelah kelas terbentuk, kita dapat menggunakan dengan membuat obyek yang merupakan instance dari kelas tersebut. Perhatikan pada bagian yang diawali dengan int main(). Pada bagian ini kita membentuk dua obyek dengan nama pp1 dan pp2 sebagai instance dari kelas PersegiPanjang. Kemudian, kita menggunakan obyek-obyek ini untuk memanggil method set_nilai dan luas() dari kelas PersegiPanjang. Ketikkan program di atas kemudian jalankan. Bagaimanakah hasilnya?
Seperti pada Java, umumnya suatu kelas akan mempunyai constructor yang digunakan untuk menginisialisasi variabel atau mengalokasikan memori. Constructor ini mempunyai nama yang sama dengan kelasnya. Di dalam suatu kelas, sebaiknya juga dibentuk method destructor. Destructor adalah kebalikan dari constructor. Tujuan utamanya adalah mengembalikan nilai variabel ke bentuk awal, dan membebaskan memori dari penggunaan variabel. Method destructor mempunyai nama yang sama dengan nama kelasnya, tetapi dengan ditambah awalan tanda ~. Perhatikan contoh penggunaan constructor dan destructor berikut.
Contoh 9.27. Constructor dan destructor.
#include <iostream>
using namespace std;
class PersegiPanjang {
int *panjang, *lebar;
public:
PersegiPanjang (int,int);
~PersegiPanjang ();
int luas () {return (*panjang * *lebar);}
};
PersegiPanjang::PersegiPanjang (int a, int b) {
panjang = new int;
lebar = new int;
*panjang = a;
*lebar = b;
}
PersegiPanjang::~PersegiPanjang () {
delete panjang;
delete lebar;
}
int main () {
PersegiPanjang pp1 (3,4), pp2 (5,6); cout << "Luas pp1: " << pp1.luas() << endl;
cout << "Luas pp2: " << pp2.luas() << endl;
return 0;
}
Inheritance
C++ juga memberikan fasilitas inheritance pada kelas. Proses pewarisan pada C++ agak lebih rumit dibandingkan dengan Java. Hal ini karena C++ memberikan kemungkinan pewarisan dengan pertimbangan hak akses. Ada dua hak akses dalam pewarisan superclass ke subclass, yaitu: public dan private.Apabila suatu kelas diturunkan sebagai public dari superclassnya, maka ketentuannya adalah sebagai berikut:
- Bagian public yang ada pada superclass akan tetap menjadi public pada subclass.
- Bagian protected yang ada pada superclass akan tetap menjadi protected pada subclassnya.
- Bagian private yang ada pada superclass tidak akan dapat diakses oleh subclass.
Apabila suatu kelas diturunkan sebagai private dari superclassnya, maka ketentuannya adalah sebagai berikut:
- Bagian public yang ada pada superclass akan menjadi private pada subclass.
- Bagian protected yang ada pada superclass akan menjadi private pada subclassnya.
- Bagian private yang ada pada superclass tidak akan dapat diakses oleh subclass.
Contoh 9.28. Pewarisan.
#include &lt;iostream&gt;
using namespace std;
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b;}
};
class CRectangle: public CPolygon {
public:
int area ()
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
int area ()
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
rect.set_values (4,5);
trgl.set_values (4,5);
cout &lt;&lt; rect.area() &lt;&lt; endl;
cout &lt;&lt; trgl.area() &lt;&lt; endl;
return 0;
}
Pada kode program di atas, CPolygon adalah superclass, sedangkan CRectangle dan CTriangle adalah subclass. Pada kelas CPolygon, variabel width dan height dideklarasikan sebagai protected, karena ditujukan untuk bisa diakses oleh subclassnya saja. Selain itu, kelas ini juga mempunyai method set_values. Kedua variabel dan method ini akan diwariskan pada subclassnya yaitu: CRectangle dan CTriangle. Perhatikan bagaimana CRectangle dan CTriangle dideklarasikan sebagai kelas turunan dari CPolygon dengan menggunakan kata kunci public. Sekarang, coba ganti kata public pada deklarasi kelas CTriangle sehingga menjadi class CTriangle: private CPolygon. Apabila kita kompilasi, maka kita akan menjumpai pesan kesalahan sebagai berikut:
Compiling source file(s)...
oo-test.cpp
oo-test.cpp: In function `int main()':
oo-test.cpp:9: error: `void CPolygon::set_values(int, int)'
is inaccessible
oo-test.cpp:28: error: within this context
oo-test.cpp:28: error: `CPolygon' is not an accessible base
of `CTriangle'
Mengapa kesalahan kompilasi bisa terjadi? Hal ini karena berlakunya aturan di atas. Method set_values pada kelas CPolygon dideklarasikan dengan public, tetapi diturunkan ke kelas CTriangle dengan private. Hal ini akan merubah method yang semula public menjadi private ketika berada pada kelas CTriangle. Tentunya kita ingat bila anggota kelas diberi hak akses private, maka ia tidak dapat diakses dari luar.
Polimorfisme
Pada C++ untuk dapat menerapkan polimorfisme, maka kita perlu menggunakan fungsi khusus yang dikenal sebagai fungsi virtual. Fungsi ini kita letakkan pada superclass, kemudian fungsi tersebut dapat kita definisikan ulang pada subclass. Perhatikan contoh berikut.Contoh 9.29. Penggunaan fungsi virtual.
#include <iostream>
using namespace std;
class AnggotaSekolah {
char* nama;
char* alamat;
public:
void SetNama(char* N) {
nama = N;
}
void SetAlamat(char* A) {
alamat = A;
}
char* GetNama() {
return nama;
}
char* GetAlamat() {
return alamat;
}
// Membuat fungsi virtual
virtual void Bekerja() {
cout<<"Bekerja"<<endl;
}
virtual void Berpakaian() {
cout<<"Berpakaian"<<endl;
}
};
class Siswa: public AnggotaSekolah {
char* Jurusan;
char* Program;
int semester;
public:
void SetJurusan(char* J) {
Jurusan = J;
}
void SetProgram(char* P) {
Program = P;
}
void SetSemester(int smt) {
semester = smt;
}
char* GetJurusan() {
return Jurusan;
}
char* GetProgram() {
return Program;
}
int GetSemester() {
return semester;
}
// override pada fungsi Bekerja
void Bekerja() {
cout<<"Bekerja menuntut ilmu"<<endl;
}
// override pada fungsi Berpakaian
void Berpakaian() {
cout<<"Berpakaian seragam putih abu-abu"<<endl;
}
};
class Guru: public AnggotaSekolah {
char* jabatan;
char* keahlian;
public:
void SetJabatan(char* jbt) {
jabatan = jbt;
}
void SetKeahlian(char* khl) {
keahlian = khl;
}
char* GetJabatan() {
return jabatan;
}
char* GetKeahlian() {
return keahlian;
}
// override pada fungsi Bekerja
void Bekerja() {
cout<<"Bekerja mengajarkan ilmu"<<endl;
}
// override pada fungsi Berpakaian
void Berpakaian() {
cout<<"Berpakaian baju seragam dinas resmi"<<endl;
}
};
// Fungsi utama int main() {
// instansiasi pada kelas AnggotaSekolah, Siswa dan Guru
AnggotaSekolah As;
Siswa Sw;
Guru Gr;
// Memanggil fungsi Bekerja dari masing-masing kelas
cout<<"Anggota sekolah sedang ";
As.Bekerja();
cout<<"Siswa sedang ";
Sw.Bekerja();
cout<<"Guru sedang ";
Gr.Bekerja();
cout<<'\n';
// Memanggil fungsi Berpakaian dari masing-masing kelas
cout<<"Anggota sekolah harus ";
As.Berpakaian();
cout<<"Siswa harus ";
Sw.Berpakaian();
cout<<"Guru harus ";
Gr.Berpakaian();
return 0;
}
Pada kode program di atas, ada dua fungsi/method virtual yaitu: Bekerja dan Berpakaian. Method ini adalah yang akan kita gunakan pada subclass, namun dengan penerapan yang lain. Perhatikan isi dari masing-masing method tersebut pada masing-masing subclass. Cara ini biasa disebut sebagai overriding. Coba kembali ke 'pemrograman berorientasi obyek dengan java' untuk memperjelas pengertian overriding. Bandingkan juga, bagaimana overriding dilakukan pada Java dan C++. Jika program di atas dijalankan, maka hasilnya akan tampak seperti pada gambar 9.9. Overloading juga dapat dilakukan pada fungsi virtual. Kita tentu masih ingat perbedaan overriding dan overloading yang sudah dijelaskan di 'pemrograman berorientasi obyek dengan java'.
Pada contoh 9.29 di atas, fungsi virtual dibuat lengkap dengan isi dari fungsi tersebut. Namun sebenarnya C++ juga menyediakan fungsi virtual murni (pure virtual function) yang hanya ada deklarasi fungsinya tapi tidak ada isinya. Konsep ini mirip dengan ketika kita memmahami tentang interface pada Java. Fungsi virtual murni ini kemudian akan diterjemahkan isinya pada kelas-kelas yang merupakan turunan dari kelas tersebut. Keuntungan dari penggunaan fungsi virtual murni ini adalah keleluasaan kita untuk mendefinisikan fungsi-fungsi tersebut pada kelas turunannya. Fungsi virtual murni biasanya digunakan pada kelas abstrak. Kelas abstrak adalah kelas yang mempunyai paling tidak satu fungsi virtual murni. Karena masih abstrak, kita tidak diperbolehkan untuk membuat obyek langsung dari kelas abstrak.
Konsep polimorfisme pada C++ disusun dengan berdasarkan pengertian pada fungsi virtual, fungsi virtual murni, overriding, overloading, dan kelas abstrak. Perhatikan contoh polimofisme berikut ini.
Contoh 9.30. Penerapan polimorfisme.
#include <iostream>
using namespace std;
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0; //fungsi virtual murni
void printarea (void)
{ cout << this->area() << endl; }
};
class CRectangle: public CPolygon {
public:
// overriding fungsi area
int area (void)
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
// overriding fungsi area
int area (void)
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
CPolygon *ppoly1 = &rect; // mendefinisikan obyek pointer
CPolygon *ppoly2 = &trgl; // mendefinisikan obyek pointer
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ppoly1->printarea();
ppoly2->printarea();
return 0;
}
Pada contoh di atas, kelas CPolygon adalah kelas abstrak yang memiliki fungsi virtual murni yaitu area. Perhatikan cara mendeklarasikan fungsi virtual murni pada baris yang diawali dengan pernyataan virtual. Fungsi ini tidak dibuat isinya tapi dibuat dengan tanda = 0. Kita tidak dapat membuat obyek langsung dari kelas CPolygon ini. Tetapi kita dapat membuat obyek pointer untuk mengalokasikan memori berdasarkan kelas ini. Pada kelas CPolygon juga digunakan kata kunci this. Kata kunci ini berfungsi untuk menunjuk pada kelas itu sediri. Pernyataan this->area() pada kode di atas sama artinya dengan CPolygon->area(). Jadi pernyataan ini sama artinya dengan memanggil fungsi virtual area di dalam kelas itu.
Pada kode diatas dibuat dua variabel pointer *ppoly1 dan *ppoly2 yang nilainya sama dengan nilai dari alamat variabel rect dan trgl. Perhatikan dengan baik penggunaan tanda * dan & untuk merujuk pada alamat memori. Jalankan program di atas dan perhatikan hasilnya.
0 komentar :
Posting Komentar
Terima kasih, atas saran atau usulan anda.