Professional Documents
Culture Documents
Diciptakan oleh Bjarne Stroustrup di AT&T Bell Laboratories pada awal 1980an Pada mulanya dikenal sebagai C with Classes (nama C++ digunakan sejak 1983, setelah diusulkan oleh Rick Mascitti). 1985: disebarluaskan oleh AT&T, perangkat lunak cfront (C++ translator). Didasarkan pada bahasa C, Simula67, Algol68, Ada.
Simula67: konsep kelas. Algol68: konsep operator overloading dan kemungkinan penempatan deklarasi di manapun Ada: konsep template dan exception
1
Class
Untuk menciptakan tipe data baru. Tipe = kumpulan representasi bit + kumpulan operasi terhadap tipe tersebut Kelas menyediakan sekumpulan operasi (biasanya public) dan sekumpulan data bit (biasanya non-public) Peran: perancang kelas dan pengguna kelas.
Perancang: menentukan representasi internal objek serta operasi yang disajikan pada pengguna kelas. Pengguna: memanfaatkan operasi tersebut untuk memanipulasi objek
Pengaturan akses terhadap anggota kelas: private, public, protected Perhatikan perubahan parameter aktual pada prosedur MoveTo
Makna dapat diakses oleh fungsi luar kelas dengan menggunakan operator selektor (. atau ->) hanya dapat diakses oleh fungsi kelas tersebut
seperti private, namun dapat diakses oleh kelas turunan Fungsi luar: fungsi yang bukan anggota kelas tersebut
class Stack { public: // function member void Pop(int& ); // deklarasi (prototype) void Push (int); // deklarasi (prototype) /*--- pendefinisian di dalam class body ---*/ int isEmpty() { return topStack == 0; } private: // data member int topStack; /* posisi yang akan diisi berikutnya */ int *data; };
// pendefinisian member function Pop di luar // class body void Stack::Pop(int& item) { if (isEmpty()) printf ("Error: stack kosong"); else { topStack--; item = data [topStack]; } } void Stack::Push (int item) { // . . . data [topStack] = item; topStack++; // . . . }
10
Manfaat: Setiap objek memiliki anggota data terpisah, namun anggota fungsi bersama, this diperlukan untuk mengakses data
11
0 ctor dan
1 dtor
Copy constructor (cctor) = konstruktor yang menciptakan objek dengan cara menduplikasi objek lain yang sudah ada
Jika tidak dideklarasikan oleh perancang kelas, cctor akan dilakukan secara bitwise copy
Untuk menciptakan array dari objek, kelas objek tersebut harus memiliki default ctor.
13
14
// Nama file: Stack.h // Deskripsi: interface dari kelas Stack #ifndef STACK_H #define STACK_H class Stack { // // anggota data dan fungsi dari kelas Stack // }; #endif STACK_H
PERHATIAN: Di dalam header le, jangan menuliskan denisi objek/variabel karena akan mengakibatkan kesalahan multiply dened name pada saat linking dilakukan.
15
// Nama file: Stack.cc // Deskripsi: implementasi/body dari kelas Stack #include "Stack.h" Stack::Stack () { // ... ctor } Stack::Stack () { // ... dtor } // dst.. dst..
16
Pemanfaatan Kelas
Perancang kelas:
1. Kompilasi le implementasi (*.cc) menjadi kode objek (*.o) 2. Berikan le header (*.h) dan le kode objek (*.o) kepada pemakai kelas (mungkin dalam bentuk library)
Pemakai kelas:
1. Sertakan le header di dalam program (main.cc) 2. Kompilasi program C++ menjadi kode objek (main.o) 3. Link main.o dengan kode objek yang diberikan perancang kelas
17
Penciptaan/Pemusnahan Objek
Beberapa jenis objek dalam program C++:
Automatic object: diciptakan melalui deklarasi objek di dalam blok eksekusi dan dimusnahkan pada saat blok tersebut selesai eksekusi Static object: diciptakan satu kali pada saat program dimulai dan dimusnahkan pada saat program selesai Free store object: diciptakan dengan operator new dan dimusnahkan dengan operator delete. Kedua operator dipanggil secara eksplisit oleh pemakai Member object: sebagai anggota dari kelas
18
#include <Stack.h> Stack s0; /* global (static) */ int reverse() { static Stack tstack; /* local static */ // kode untuk fungsi reverse() di sini }
// automatic // automatic
s3 = Stack (5); // ctor Stack(5) is called /* dtor Stack(5) is called */ //... } /* dtor s3 is called */ delete ptr; /* dtor *ptr is called */ } /* dtor s2 is called */ /* dtor s1 is called */ /* dtor s0 is called */
Copy Constructor
Copy constructor (cctor) dipanggil pada saat penciptaan objek secara duplikasi:
Deklarasi variabel dengan inisialisasi Passing parameter aktual ke parameter formal secara pass by value Pemberian return value dari fungsi yang nilai kembaliannya bertipe kelas tersebut (bukan ptr/ref)
20
class Stack { public: Stack(); // Stack (int); // Stack (const Stack&); // Stack(); // //... };
Stack::Stack (const Stack& s) { size = s.size; topStack = s.topStack; data = new int [size]; // PERHATIKAN: member "data" // harus di alokasi ulang, // tidak disalin dari "s.data". int i; for (i=0; i<topStack; i++) data[i] = s.data[i]; }
21
#include <Stack.h> f (Stack _) { // ... } Stack ll; main() { Stack x; Stack y = x; f(x); }
22
Urutan pemanggilan: ctor Stack (2), ctor String, lalu ctor Parser. sym_stack akan diinisialisasi oleh constructor Stack::Stack().
23
Jika ctor yang diinginkan adalah Stack::Stack(int), maka ctor Parser::Parser() harus melakukan constructor initialization list
24
Parser::Parser(int x) : { // ... }
Initialization list dapat berisi
1 inisialisasi
Setiap inisialisasi mencantumkan nama data anggota (atau nama kelas) dengan parameter aktual untuk ctor kelas anggota
25
Const Member
Atribut const dapat diterapkan pada anggota data maupun anggota fungsi
Pada anggota data: nilai anggota data tersebut akan tetap sepanjang waktu hidup objeknya.
Pengisian nilai awal harus dilakukan pada saat objek tersebut diciptakan, yaitu melalui constructor initialization list (hanya untuk ANSI)
Pada anggota fungsi: fungsi tersebut tidak akan mengubah (status) objek yang memanggilnya.
Object yang ditandai sebagai const tidak boleh memanggil fungsi anggota yang tidak memiliki atribut const
26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Stack { public: int isEmpty() const; private: const int size; }; int Stack::isEmpty () const { return topStack == 0; } Stack::Stack () : size (defaultStacksize) { }
27
Setiap objek dari kelas memiliki sendiri salinan anggota data non-statik Anggota data statik dipakai bersama oleh seluruh objek dari kelas tersebut
28
29
30
31
Friend
Friend = pemberian hak pada fungsi / kelas untuk mengakses anggota non-public suatu kelas.
1 2 3 4 class B { // kelas "pemberi ijin" friend class A; friend void F (int, char *); };
Friend bersifat satu arah Seluruh fungsi anggota kelas A dan fungsi F dapat mengakses anggota non-public dari kelas B
parameter aktual mungkin dilewatkan secara call-by-value. Akibatnya operasi yang dilakukan terhadap objek bukanlah objek semula.
33
Nested Class
34
Operator Overloading
int a, b, c; float x, y, z; c = a + b; z = x + y; /* "fungsi +" di-overload */
35
Fungsi operator
Fungsi operator = fungsi namanya adalah operator @ (@ diganti dengan simbol operator yang ada. Dapat dimanfaatkan dalam pemanipulasian objek dengan menggunakan simbol
Matrix A, B, C; C = A * B; /* perkalian matrix */ Complex x, y, z; x = y / z; /* pembagian bilangan kompleks */ Process p; p << SIGHUP; /* pengiriman sinyal dalam Unix */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
class Matrix { public: // fungsi-fungsi operator friend Matrix& operator* (const Matrix&, const Matrix&); }; class Complex { // ... public: Complex& operator/ (const Complex&); }; class Process { // ... public: void operator<< (int); };
37
Jika mengakses anggota yang non-public maka fungsi tersebut harus dideklarasikan sebagai friend Jumlah parameter formal = jumlah operand
Sebagai anggota
Dideklarasikan pada wilayah public Parameter pertama dari operasi harus bertipe kelas tersebut Jumlah parameter formal = jumlah operand 1
38
40
41
Error terdeteksi pada saat kompilasi karena kelas Stack tidak memiliki fungsi operator<<.
42
43
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Stack { // dalam contoh ini friend tidak diperlukan friend void operator+ (Stack&, int); friend void operator+ (int, Stack&); //... }; void operator+ (Stack& s, int m) { s.Push (m); } void operator+ (int m, Stack& s) { s.Push (m); }
44
45
Beberapa manfaat fungsi operator: 1. Operasi aritmatika terhadap objek-objek matematik lebih terlihat alami dan mudah dipahami oleh pembaca program. c = a*b + c/d + e; // lebih mudah dimengerti c = tambah (tambah (kali (a,b), bagi(c,d)), e); 2. Dapat menciptakan operasi input/output yang seragam dengan memanfaatkan stream I/O dari C++. 3. Pengalokasian dinamik dapat dikendalikan perancang kelas melalui fungsi operator new dan delete. 4. Batas index pengaksesan array dapat dikendalikan lewat operator [].
46
Fungsi operator harus merupakan member atau paling sedikit salah satu argumen berasal dari kelas yang dioperasikan
48
Operator =
Assignment copy constructor
Pada assignment a = b, objek a dan b sudah tercipta sebelumnya Pada copy constructor Stack s = t;, hanya (t) yang sudah tercipta, objek s sedang dalam proses penciptaan.
Stack& Stack::operator= (const Stack& s) { /* assign stack "s" ke stack "*this" */ int i;
delete [] data; // bebaskan memory yang digunakan sebelumnya size = s.size; data = new int [size]; // alokasikan ulang topStack = s.topStack; for (i=0; i<topStack; i++) data [i] = s.data[i];
49
return *this; }
50
Assignment berantai dapat diterapkan pada objek dari kelas, jika nilai kembali operator= = reference.
Fungsi anggota operator= harus memberikan nilai kembali berupa objek yang sudah mengalami operasi assignment (perintah return *this.)
51
// ... };
53
Operator[]
Dapat digunakan untuk melakukan subscripting terhadap objek. Jika digunakan sebagai subscripting batas index dapat diperiksa Parameter kedua (index/subscript) dapat berasal dari tipe data apapun: integer, oat, character, string, maupun tipe/kelas yang didenisikan user.
54
Template Function
Kebutuhan: operasi yang sejenis terhadap tipe yang berbeda-beda.
int min(int a, int b) { return a < b ? a : b; } float min(float a, float b) { return a < b ? a : b; } // dst...
55
Substitusi Makro
Trick yang biasa digunakan adalah dengan denisi makro
#define mmin(a,b) ((a) < (b) ? (a) : (b)) Contoh pemanfaatan: if (mmin (x++, y) == 0) printf ("...."); hasil ekspansi makro: if (((x++) < (y) ? (x++) : (y)) == 0) printf ("....");
Substitusi makro
pemanggilan fungsi
56
Template: deklarasi fungsi generik yang dapat diinstansiasi bergantung pada tipe yang diperlukan pemakai. Instansiasi dilakukan oleh kompilator pada saat mengetahui ada pemanggilan fungsi pada nama generik tersebut.
57
Contoh lain:
template <class Type> Type min_arr (const Type x[], int size) /* mencari minimum dari array */ { Type min_val; int i; min_val = x[0]; for (i=1; i<size; i++) { if (x[i] < min_val) min_val = x[i]; } return min_val; }
58
Nama tipe yang dicantumkan di antara < dan > harus tercantum sebagai function signature.
template <class T1, class T2, class T3> T1 myFunc (T2 a, T3 b) /* error: T1 bukan bagian dari signature */ { /* ... */ }
59
60
Class Template
Konsep template dapat diterapkan juga pada kelas untuk menghasilkan kelas generik Kelas Stack generik dapat diinstansiasi sebagai Stack of integer, Stack of double, Stack of character, Stack of Complex, Stack of Process, Stack of String, dsb. Penciptaan objek kelas generik kls-generik < tipe-instansiasi > objek ; Stack<int> a; Stack<double> b (30); Stack<Complex> c; // Stack of integer // Stack of double, kapasitas m // Stack of Complex
62
Penulisan Kode
Kelas non-generik:
Deklarasi / interface dituliskan di XXXX.h Denisi fungsi anggota / implementation dituliskan di XXXX.cc
Kelas generik: Deklarasi (interface) maupun denisi fungsi anggota (implementation) dituliskan di XXXX.h Nama kelas yang sudah instansiasi merupakan nama tipe baru Nama tipe instansiasi dapat juga digunakan di dalam kelas untuk mendeklarasikan objek bertipe generik.
template <class Type> void Stack<Type>::Reverse() { Stack<Type> stemp; // objek lokal yang generik // ...algoritma dari Reverse()...
64
65
66
1. Bagian yang diturunkan dari B, dan 2. Bagian yang didenisikan sendiri (spesik terhadap A) 3. Fungsi di dalam kelas turunan dapat mengakses semua anggota (fungsi/data) di dalam bagian non-private.
67
68
Perubahan tingkat pengaksesan akibat pewarisan: Tingkat-Akses di kelas dasar protected public private private private Mode-pewarisan protected protected protected public protected public
private: = sangat tertutup (hanya fungsi anggota kelas tersebut yang dapat mengakses, public: = sangat terbuka (fungsi manapun, di dalam atau di luar kelas dapat mengakses anggota dalam bagian ini), protected: setengah terbuka / setengah tertutup (hanya kelas turunan yang dapat mengakses anggota pada bagian ini).
69
Contoh Pewarisan
Growing Stack: Stack yang kapasitasnya dapat bertambah/berkurang secara otomatis Push(): jika Stack penuh perbesar kapasitas Pop(): jika kapasitas tak terpakai cukup besar perkecil kapasitas Kelas GStack dapat diwariskan dari kelas Stack dengan cara : 1. Mengubah perilaku Pop() dan Push() yang ada pada kelas Stack 2. Menambahkan anggota data yang digunakan untuk menyimpan faktor penambahan/penciutan kapasitas stack
70
// File GStack.h // Deklarasi kelas GStack #ifndef GSTACK_H #define GSTACK_H #include "Stack.h" class GStack : public Stack { public: // ctor, cctor, dtor, oper= (tidak dituliskan)
71
// redefinition of Push & Pop void Push (int); void Pop (int&); private: int gs_unit; // fungsi untuk mengubah kapasitas void Grow(); void Shrink(); }; #endif GSTACK_H
// File GStack.cc // Definisi fungsi-fungsi anggota kelas GStack #include <stdio.h> #include "GStack.h" void GStack::Push (int x) { if (isFull()) Grow(); Stack::Push(x); } void GStack::Pop (int& x) { Stack::Pop(x); if (size - topStack > gs_unit) Shrink(); }
72
73
74
Penginisialisasian kelas dasar oleh kelas turunan melalui ctor atau cctor dilakukan melalui constructor initialization list
1 2 3 4 5 6 7 8 9 // File GStack.cc // Definisi fungsi-fungsi anggota kelas GStack #include <stdio.h> #include "GStack.h" GStack::GStack(const GStack& s) : Stack (s) { gs_unit = s.gs_unit; }
75
Polymorphism
Objek-objek dari kelas turunan memiliki sifat sebagai kelas tersebut dan sekaligus kelas dasarnya.
ref/ptr memiliki tipe statik dan tipe dinamik. Tipe statik = tipe objek pada saat deklarasikan Tipe dinamik = tipe objek yang berubah pada saat eksekusi, bergantung pada objek yang diacu
77
Dynamic Binding
Tipe dinamik dari digunakan pada saat eksekusi untuk memanggil fungsi anggota yang berasal dari kelas berbeda-beda melalui sebuah ref/ptr dari kelas dasar. Fungsi yang akan dipanggil secara dinamik, harus dideklarasikan sebagai virtual (dilakukan di kelas dasar). Dalam contoh GStack fungsi Push() dan Pop() akan dipanggil secara dinamik Kelas Stack harus mendeklarasikan sebagai fungsi virtual
78
1 2 3 4 5 6 7 8 9 10 11
// File: Stack.h class Stack { public: // ctor, cctor, dtor, & oper= public: // services virtual void Push (int); virtual void Pop (int&); };
79
#include <GStack.h> // tipe memiliki tipe dinamik void FuncVal (Stack s) { s.Push (10); } // memiliki tipe dinamik void FuncPtr (Stack *t) { t->Push (10); } // memiliki tipe dinamik void FuncRef (Stack& u) { u.Push (10); } main() { GStack gs; FuncVal (gs); // Stack::Push() dipanggil FuncPtr (&gs); // GStack::Push() dipanggil FuncRef (gs); // GStack::Push() dipanggil }
80
Virtual Destructor
Stack* sp [MAX_ELEM]; // ... kode-kode lain for (i=0; i<MAX_ELEM; i++) delete sp[i]; // tipe elemen: Stack/ GStack !
Destruktor mana yang akan dipanggil delete sp[i];? Diperlukan virtual destructor
class Stack { public: // ctor, dtor, cctor //... virtual Stack(); // };
81
Di dalam kelas turunan (GStack), destruktor tidak perlu dideklarasikan virtual karena otomatis mengikuti jenis dtor kelas dasar.
82
Tidak dapat diimplementasikan di dalam kelas Shape, namun harus dideklarasikan. Dideklarasikan sebagai fungsi pure virtual.
ABC = kelas yang memiliki fungsi pure virtual
83
class DataStore { public: // ... virtual void Clear() = 0; // pure virtual // ... };
Tidak ada objek yang dapat dibuat dari kelas dasar abstrak Di dalam kelas non-abstrak (yang mewarisi kelas dasar abstrak) fungsi pure virtual harus diimplementasikan.
84
// File: Stack.h // Deskripsi: deklarasi kelas Stack yang diturunkan dari DataSt class Stack : public DataStore { public: // ... void Clear (); };
// File: Tree.h // Deskripsi: deklarasi kelas Tree yang diturunkan dari DataSto class Tree : public DataStore { public: // ... void Clear (); };
85
Exception
Penambahan kode khusus untuk menangani kesalahan dalam eksekusi program membuat program menjadi rumit
1 2 3 4 5 6 7 8 int LakukanAksi () { // ... if ( .... ) // periksa kondisi kesalahan return NILAI_KHUSUS; else return NILAI_FUNGSI; }
86
1 2 3 4 5 6 7 8 9
if (LakukanAksi () == NILAI_KHUSUS) { // ... jalankan instruksi untuk menangani kesalahan } else { // instruksi-1 // instruksi-2 // ... // instruksi-n }
87
Exception
Kesalahan dalam eksekusi program = exception Penanganan exception dalam C++: throw, catch dan try.
return = kembali dari fungsi dengan normal throw = kembali dari fungsi dengan abnormal (exception).
1 2 3 4 5 6 7 8 int LakukanAksi () { // ... if ( .... ) // periksa kondisi kesalahan throw "Ada kesalahan"; else return NILAI_FUNGSI; }
89
Exception Handler
Perintah dalam blok catch = exception handler. Sebuah blok try dapat memiliki exception handler, masing-masing untuk menangani tipe exception yang berbeda. Tipe handler ditentukan signaturenya. Catch-All handler memiliki signature ....
try { // } catch // } catch // } instruksi... (StackErr&) { handler untuk tipe "StackErr" (...) { handler untuk semua jenis exception lainnya
90
Pemilihan Handler
1. Jika terjadi exception hanya satu handler yang dipilih berdasarkan signature-nya 2. Instruksi di dalam handler yang terpilih dijalankan 3. Eksekusi dari blok try tidak dilanjutkan 4. Eksekusi berlanjut ke bagian yang dituliskan setelah bagian try-catch tersebut.
91
92
93
// raise exception
// raise exceptio
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include "Stack.h" #include <stdio.h> main() { Stack s; int n; try { // ... s << 10; // ... } catch (StackExp& s) { s.DisplayMsg(); } n = StackExp::NumException(); if (n > 0) printf ("Muncul %s stack exception\n", n); }
95
stdio.h: stream.h:
Mengapa stream?
1 2 3 4 5 6 7
template <class T> class Stack { public: // ... void Cetak() const; // ... };
96
97
Jenis elemen array data primitif / non-primitif? Untuk tipe Stack<Process>: cout << data[i] akan dilakukan melalui 1. anggota dari kelas cout stream::operator<< (const Process&); atau 2. fungsi non-anggota operator<< (stream&, const Process&); Salah satu dari fungsi tersebut harus didenisikan oleh perancang kelas Process. Alternatif 1 tidak mungkin dilakukan (mengubah deklarasi kelas stream)
98
99
Keuntungan penggunaan kelas stream: 1. Type safety: tipe objek diketahui pada saat kompilasi 2. Extensible: fungsi operator<< dan operator>> pada kelas stream dapat di-overload untuk kelas baru 3. Mengurangi kesalahan pemakaian
100
3. iostream: stream dua arah (input/output) (diturunkan dari istream dan ostream) Manipulasi terhadap le disediakan kelas-kelas berikut: 1. ifstream yang diturunkan dari kelas istream 2. ofstream yang diturunkan dari kelas ostream 3. fstream yang diturunkan dari kelas iostream
101
Contoh
cout << objek/nilai-yang-dicetak; cin >> objek-yang-menerima-nilai; Pembacaan input dalam loop:
1 2 3 4 5 6 7 8 9 10 #include <stream.h> main () { char ch; while ( cin >> ch ) { // ... } } // FALSE jika mendapatkan EOF
103