• Tidak ada hasil yang ditemukan

BAB 14 OPERATOR OVERLOADING

N/A
N/A
Protected

Academic year: 2022

Membagikan "BAB 14 OPERATOR OVERLOADING"

Copied!
71
0
0

Teks penuh

(1)

BAB 14

OPERATOR OVERLOADING

14.1 Pendahuluan

Seperti halnya pada fungsi, C + + juga mengizinkan kita untuk melakukan overload terhadap operator. Ini berarti bahwa operator tersebut dapat kita gunakan sesuai kebutuhan yang kita inginkan sendiri. Sebagai contoh, C++ sendiri sebenarnya telah melakukan overload terhadap operator +, sehingga operator ini dapat berlaku untuk menjumlahkan nilai yang bertipe bilangan bulat (seperti int dan long) maupun floating-point (seperti float dan double).

Pada bagian ini kita akan mempelajari bagaimana konsep dasar untuk membuat suatu operator dapat bekerja sesuai yang kita harapkan.

Konsep dasar yang harus dimiliki untuk dapat melakukan overload terhadap operator adalah dengan mendefinisikan suatu fungsi, yaitu yang dikenal dengan sebutan fungsi operator. Untuk membuat fungsi ini digunakan kata kunci operator. Fungsi operator kebanyakan berperan sebagai anggota (member function) dari suatu kelas. Kalaupun tidak, maka fungsi tersebut biasanya merupakan suatu friend function. Terdapat perbedaan antara penulisan fungsi untuk pembuatan fungsi operator yang merupakan anggota kelas dan yang bukan. Berikut ini bentuk umum pembuatan fungsi operator yang merupakan anggota dari suatu kelas.

Bab 14: Operator Overloading

(2)

tipe_kembalian namajkelaa s t operator* (daftar_jparameter) // Operas! yang akan dilakukan

Pada bentuk umum di atas, nama_kelas adalah nama dari kelas pemilik fungsi tersebut. Sedangkan tanda # di atas berfungsi sebagai placeholder, artinya di sinilah kita mendefinisikan operator apa yang akan kita overload. Apabila kita ingin melakukan overload terhadap operator +, maka penulisan fungsinya adalah operator*. Begitu pula jika kita akan melakukan overload terhadap operator /, maka kita akan menulisnya operator/.

Sedangkan bentuk umum dari pembuatan fungsi yang bukan merupakan anggota kelas (yang bias any a adalah friend function) adalah sama seperti pendefinisian fungsi biasa, yaitu sebagai berikut :

tlpejMunbalian operator* (daf tar__parameter) // Operas! yang akan dilakukan

14.2 Operator yang Tidak Dapat D\-Overload

Meskipun C++ telah memberikan kebebasan kepada kita untuk melakukan overload, namun ada beberapa operator yang tidak diizinkan untuk di-overload. Berikut ini operator-operator yang dimaksud di atas.

, r *: : •.VffeeV;'- •--.'•

Selain itu kita juga tidak diizinkan untuk melakukan overload terhadap simbol preprocessor, yaitu # dan ##.

Untuk lebih jelasnya, berikut ini operator-operator yang dapat kita overload.

a. Operator Unary + - * & ~ b. Operator Binary

+ - * / % - &

++ -- -> ->*

new[] delete delete []

Pemrograman C++

14.3 Melakukan Overload terhadap Operator Binary

Pada bagian ini kita akan membahas mengenai overload terhadap operator binary, sedangkan operator unary akan dibahas pada sub bab selanjutnya di dalam buku ini. Hal ini dimaksudkan agar Anda dapat lebih memahami konsepnya terlebih dahulu. Adapun operator binary yang akan di-over/oad di sini hanyalah tiga, yaitu operator +, - dan =. Ini disebabkan karena Anda tentu sudah familiar dengan penggunaan operator-operator tersebut. Untuk lebih lengkapnya, diharapkan Anda dapat mengembangkannya sendiri dengan berbekal konsep-konsep yang telah di dapat pada bab ini. Berikut ini penjelasan mengenai cara-cara melakukan overload terhadap operator-operator yang dimaksud di atas.

14.3.1 Overload Operator +

Di sini kita akan membuat program yang di dalamnya terdapat overload operator plus (+) sehingga operator tersebut dapat menjumlahkan dua buah nilai yang bertipe objek. Fokuskan perhatian Anda ke pembuatan fungsi operator di bawah ini.

Adapun sintaks programnya adalah sebagai berikut.

using namespace std;

// Membuat kelas TITIK class TITIK {

int X, Y;

public:

// Membuat fungsi constructor untuk kelas TITIK TITIK(int XX, int YY) {

X = XX;

Y = YY;

// Membuat fungsi ShowXY

| void ShowXY() {

cout«"Nilai X : "«X«endl;

cout«"Nilai Y : "«Y«endl;

// Mendeklarasikan fungsi operator yang mengembalikan Bab 14: Operator Overloading

(3)

T

/ objek TITIK

ITIK TITIK::operator +(TITIK P) ;

// Implementasi dari fungsi operator di atas TITIK TITIK::operator +{TITIK P) {

.return TITIK(P.X + X, P.Y + Y);

// Fungsi utama int main() {

// Melakukan instansiasi terhadap kelas TITIK TITIK A(2, 3);

TITIK B(5, 4);

// Menampilkan nilai X dan Y yang terdapat pada objek A dan A.ShowXYO ;

cout«endl ; B.ShowXY(};

cout«endl ;

// Menjumlahkan objek A dan B dan menyimpannya ke objek TITIK C = A + B;

// Menampilkan nilai X dan Y yang terdapat pada objek C C.ShowXY();

return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Nilai X : 2 Nilai Y : 3 Nilai X : 5 Nilai Y : 4 Nilai X : 7 Nilai Y : 7

Seperti yang kita lihat di atas bahwa operator + dapat kita gunakan untuk menjumlahkan dua buah objek bertipe TITIK. Secara default, operasi ini tentu tidak diperbolehkan oleh kompiler. Namun

Pemrograman C++

dengan melakukan overload terhadap operator tersebut, maka kita dapat melakukannya.

14.3.2 Overload Operator -

Untuk melakukan overload terhadap operator -- tentu prinsipnya sama dengan overload terhadap operator + di atas. Namun, sebagai pengetahuan bagi Anda, kita akan melakukan modifikasi terhadap program di atas dengan menambahkan fungsi operator untuk operator -. Adapun sintaks programnya adalah sebagai berikut:

#include <iostream>

using namespace std;

class TITIK .{

int X, Y;

public:

// Membuat fungsi SetXY dan ShowXY void SetXY (int XX, int YY) {

X = XX;

Y = YY;

void ShowXY () { cout«"Nilai X cout«"Nilai Y

«X«endl;

«Y«endl;

// Mendeklarasikan fungsi operator untuk TITIK TITIK: : operator -(TITIK P) ;

// Implementasi dari fungsi operator di atas TITIK TITIK::operator -(TITIK P) {

TITIK temp; // Membuat objek temporary yang bertipe temp.X = X - P . X ;

tertp.Y = Y - P.Y;

return temp;

// Fungsi utama nt main() {

// MelaJcu/can instansiasi terhadap kelas TITIK

• TITIK A, B, C;

// Mengeset nilai X dan Y untuk objek A dan B Bab 14: Operator Overloading

(4)

uSetXY(10, 6);

|.SetXY(4,2) ;

// Menampilkan nilai X dan Y yang terdapat pada objek A

\ , ShowXY ( ) ; :out«endl ;

// Menampilkan nilai X dan Y yang terdapat pada objek A B . ShowXY ( ) ;

cout«endi ;

// Melakukan pengurangan terhadap objek A dan B C = A - B;

// Menampilkan nilai X dan Y yang terdapat pada objek C C . ShowXY ( ) ;::

return 0;

Apabila dijalankan program di atas akan memberikan hasil sebagai berikut :

Nilai X : 10 Nilai Y : 6 Nilai X : 4 Nilai Y : 2 Nilai X : 6 Nilai Y : 4

14.3.3 Overload Operator =

Pada bagian ini kita akan melakukan overload terhadap operator =.

Sebelumnya kita telah mengetahui bahwa operator = digunakan untuk melakukan assigment suatu nilai ke dalam suatu variabel.

Namun di sini, kita akan menjadikan operator tersebut bekerja untuk assignment nilai ke dalam sebuah objek. Prinsip kerjanya sama dengan layaknya fungsi yang digunakan untuk pengesetan nilai (misalnya SetX ( ) ) . Untuk lebih memahaminya, perhatikan dahulu program di bawah ini, dimana nilai diset melalui fungsi.

Adapun sintaksnya adalah sebagai berikut:

Pemrograman C+^

Kode Program 14-3 Mncl.ude <iostream>

using namespace std;

class CONTOH { int X;

public:

t void SetX(int XX) { X = XX;

int GetXO { return X;

// Fungsi utama int main() {

// Melakukan instansiasi terhadap kelas CONTOH CONTOH A;

:,// Memasukkan nilai 5 ke variabel X yang terdapat // pada kelas CONTOH

A.SetX(5);

// Menampilkan nilai X cout«"Nilai X : M«A.GetX();

return

Seperti yang kita lihat di atas bahwa untuk memasukkan nilai ke dalam variabel X yang terdapat pada objek A, kita menggunakan fungsi SetX ( ) . Di sini kita tidak dapat melakukannya dengan menggunakan operator =, yaitu dengan statemen :

A = 5; // SALAH, tidak diizinkanoleh kompiler : :; Namun, untuk mengatasi kasus seperti ini, sebenarnya kita dapat melakukan overload terhadap operator =. Berikut ini contoh program yang akan menunjukkan hal tersebut.

"—^^^^^^^•••fmmmmmmiimmmfmmmammmm

#include <iostream>

using namespace std;

class CONTOH {

Bab 14: Operator Overloading

(5)

int X;

public:

int GetXf return X;

|// Membuat fungsi operat fint operator =(int nila^.{

X = nilai;

return 1; // return true

// Fungsi utama int main() {

// Melakukan instansiasi terhadap kelas CONTOH CONTOH A;

// Memasukkan nilai 5 ke variabel X yang terdapat // pada kelas CONTOH

A » 5; // Sebenarnya memanggil A.operator"(5) // Menampilkan nilai X

cout«"Nilai X : "«A.GetX(

return 0;

86/"?«v-

Apabila kedua program di atas dijalankan, maka akan memberikan hasil yang sama, yaitu sebagai berikut:

Nilai X : 5

14.4 Melakukan Overload terhadap Operator Unary

Selain operator binary, kita juga dapat melakukan overload terhadap operator-operator unary. Adapun contoh yang akan kita bahas di sini hanya mencakup operator increment ( + + ) dan decrement (--) iaja.

14.4.1 Overload Operator ++

Secara default, dalam C + + operator increment (++) digunakan untuk menambahkan nilai satu terhadap suatu variabel yang

Pemrograman C-

bertipe bilangan bulat, bilangan floating-point maupun karakter.

Namun di sini, kita akan melakukan overload terhadap operator tersebut sehingga dapat bekerja untuk tipe objek. Adapun kelas yang akan diambil sebagai contoh di sini adalah kelas titik (yang mempunyai data X dan Y). Pada contoh ini, setiap increment objek maka nilai X dan Y dari objek tersebut secara otomatis akan bertambah satu. Berikut ini sintaks program yang menunjukkan hal tersebut.

Kode Program 14-5

#include <iostream>

using namespace std;

class TITIK {

int X, Y;

public :

// Membuat fungsi constructor untuk kelas TITIK TITIK (int XX, int YY) {

X = XX;

Y = YY;

// Membuat fungsi ShowXYO void ShowXYO {

cout«"Nilai X : "«X«endl;

cout« "Nilai Y : "«Y«endl;

// Membuat fungsi operator untuk pre- increment TITIK operator ++ ( ) {

X += 1; // dapat dituliskan X = X + 1 Y += 1; // dapat dituliskan Y = Y + 1

return *this;

.// Membuat fungsi operator untuk post- increment TITIK operator ++(int) {

X += 1;

Y += 1;

return *this;

};

// Fungsi utama int main() {

// Mela^uJcai! instansiasi terhadap kelas TITIK A(2, 4);

// Melakukan pre-increment terhadap obje.

cout«"Pre--increment untuk objek A"«end ++A;

Bab 14: Operator Overloading

(6)

.

// Menampilkan nilai X dan Y yang terdapat pada objek A A.ShowXYO ;

cout«endl ;

// Melakukan instansiasi terhadap kelas TITIK TITIK B(10, 5) ;

// Melakukan post-increment terhadap objek B cout« "Post-increment untuk objek B"«endl;

B++;

// Menampilkan nilai X dan Y yang terdapat pada objek B B.ShowXY();

return 0;

i

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Pre-increment untuk objek A Nilai X : 3

Nilai Y : 5

Post-increment untuk objek B Nilai X: 11

Nilai Y : 6

14.4.2 Overload Operator - -

Masih seputar kelas TITIK, di sini kita akan menjadikan operator decrement (--) dapat bekerja untuk objek yang bertipe TITIK.

Sebenarnya prinsip yang terdapat di dalamnya adalah sama saja dengan overload terhadap operator increment (++) di atas. Untuk lebih jelasnya, perhatikan contoh program di bawah ini.

using namespace std;

class TITIK int X, public:

IK {

Pemrograman C++

// Membuat fungsi constructor untuk kelas TITIK TITIK (int XX, int YY) {

X = XX;

Y = YY;

} #*'

// Membuat fungsi ShowXY() void ShowXY() {

cout«"Nilai X : "«X«endl;

cout«"Nilai Y : K«Y«endl;

// Membuat fungsi operator untuk pre-increment TITIK operator --() {

X -= 1; // dapat dituliskan X = X - 1 Y -= 1; // dapat dituliskan Y = Y - 1

return *this;

// Membuat fungsi operator untuk post-increment TITIK operator —(int) {

X -= 1;

Y -= 1;

return *this;

// Fungsi utama int main() {

// Melakukan instansiasi terhadap kelas TITIK TITIK A(10, 20);

-// Melakukan pre-decrement terhadap objek A cout«"Pre-decrement untuk objek A"«endl;

;~A; :

// Menampilkan nilai X dan Y yang terdapat pada objek A.ShowXYO ;

cout«endl ;

// Melakukan instansiasi terhadap kelas TITIK

"TITIK B(2, 6);

// Melakukan post-decrement terhadap objek B cout«"Post-decrement untuk objek B"«endl;

B--;

// Menampilkan nilai X dan Y yang terdapat pada objek B.ShowXY();

return 0;

Bab 14: Operator Overloading

(7)

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Pre-decrement untuk objek A Nilai X : 9

Nilai Y : 19

Post-decrement untuk objek B Nilai X : 1

Nilai Y : 5

14.5 Melakukan Overload terhadap Operator Khusus

Seperti yang telah dikemukakan sebelumnya, C++ mengizinkan kita untuk melakukan overload terhadap operator-operator khusus selain dari operator binary dan unary. Adapun operator khusus yang akan dibahas sebagai contoh di sini hanyalah operator new dan delete. Hal ini disebabkan karena pada prakteknya dalam kebanyakan program C + + sering sekali ditemui adanya overload terhadap kedua buah operator ini.

14.5.1 Overload Operator new

Dalam C+ + , kita juga dapat melakukan overload terhadap operator new sehingga kita dapat melakukan pengalokasian secara khusus untuk suatu tipe ataupun kelas tertentu. Adapun bentuk umum untuk membuat fungsi operator untuk operator new yang telah ditentukan dalam C + + adalah sebagai berikut:

void "operator new(slze_t size) {

// Statemen untuk menjalankan alokasi memori

••••// Jika alokasi gagal/ lemparkan eksepsi Jbad_alloc return pointer/

1

Pada bentuk umum di atas, size_t adalah suatu tipe yang telah didefinisikan di dalam C++ (hampir sama dengan tipe unsigned integer).

Pemrograman C++

Sebagai contoh di sini kita akan melakukan overload terhadap operator new untuk kelas titik, dimana apabila kita melakukan pengalokasian memori untuk kelas titik tersebut, maka operator new yang akan dipanggil oleh kompiler adalah operator yang telah kita definisikan sendiri, bukan operator new yang telah terdefinisi dalam C + +. Untuk lebih memahaminya, berikut ini sintaks program yang menunjukkan hal tersebut.

#include <iostream>

#include <cstdlib>

#include <new>

using namespace std;

Kode Program 14-7

// Untuk menggunakan fungsi malice () // Untuk menggunakan eksepsi bad_alloc

class TITIK { int X, Y;

public:

TITIK(int XX, int YY) { X = XX;

Y = YY;

void ShowXYO {

cout«"Nilai X : "«X«endl;

cout«"Nilai Y : "«Y«endl;

// Membuat fungsi operator untuk operator new void *operator new(size_t size) {

void *P;

cout«"Operator new yang didefinisikan sendiri"<

// Melakukan alokasi memori P = malloc(size);

// Jika gagal, lemparkan eksepsi bad_allo if (!P) { ~

bad_alloc BA;

throw BA?

).

return P;

// Fungsi utama int main() {

// Mendeklarasikan pointer PT yang akan menunjuk tipe TiTlf TITIK '*PT;

Bab 14: Operator Overloading

(8)

'/ Melakukan alokasi dengan operator new

;ry {

PT = new TITIK (2, 5) ; // Menampilkan nilai X dan Y PT->ShowXY() ;

} catch (bad_alloc E) {

cout«"Alokasi untuk PT gagal "«endl;

return 1;

// Mendealokasikan memori delete PT;

// Mendeklarasikan pointer yang akan menunjuk ke tipe int int *PI;

PI = new i n t ;

*PI = 3 0 0 ;

cout«"\nNilai *PI : "«*Pl«endl;

return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut :

Operator new yang didefinisikan sendiri Nilai X : 2

Nilai Y : 5 Nilai *PI : 300

Seperti yang kita lihat di atas bahwa pada saat kita mengalokasikan tipe TITIK, maka yang akan dipanggil adalah operator new yang kita definisikan sendiri. Namun pada saat kita mengalokasikan tipe int, operator new yang digunakan adalah operator new asli yang terdapat pada C + + . Sebagai bukti, di saat ki.a mengalokasikan tipe int, kita tidak melihat adanya teks

"Operator new yang didefinisikan sendiri".

Untuk operator delete di atas juga menggunakan operator yang telah terdefinisi secara default dalam C + + . Walaupun demikian, kita juga dapat melakukan overload terhadap operator delete seperti yang akan dibahas pada sub bab di bawah ini.

Pemrograman C++

14.5.2 Overload Operator delete

Pada bagian ini kita akan membahas overload untuk operator delete melalui sebuah contoh program. Namun sebelumnya kita harus mengetahui terlebih dahulu bentuk umum untuk pembuatan fungsi operator untuk operator delete, yaitu seperti yang tampak di bawah ini.

void operator delete (void *p) {

// Mendealokasikan memori yang ditunjuk oleh pointer p

Adapun program yang akan dituliskan di bawah ini merupakan modifikasi dari program di atas. Di sini, kita akan melakukan overload terhadap operator delete sehingga dapat digunakan secara khusus untuk kelas TITIK. Berikut ini sintaks program yang dimaksud.

Kode Program 14-8

tinclude <iostream>

#include <cstdlib> // Untuk menggunakan fungsi mallocO // dan freeO

#include <new> // Untuk menggunakan eksepsi bad_alloc using namespace std;

class TITIK { int X, Y;

public :

TITIK (int XX, int YY) { X = XX;

Y = YY;

void ShowXYO { cout«"Nilai X cout« "Nilai Y I

"«X«endl;

"«Y«endl;

// Membuat fungsi operator untuk operator new

| void *operator new(size_t size) { void *P;

cout«"0perator new yang didefinisikan sendiri"«end^

// Melakukan alokasi memori P - malloc(size);

// Jika gagal, lemparkan eksepsi bad_alloc if (!P) {

bad_alloc BA;

throw BA;

Bab 14: Operator Overloading

(9)

return P;

// Membuat fungsi operator untuk operator delete void operator delete(void *P) {

cout«"Operator delete yang didefinisikan sendiri"«endl;

free(P);

};

// Fungsi utama int main(} {

// Mendeklarasikan pointer PT yang akan menunjuk tipe TITIK TITIK *PT;

// Melakukan alokasi dengan operator new try {

PT = new T I T I K ( 2 , 5 ) ;

// Menampilkan nilai X dan Y PT->ShowXY();

catch (bad_alloc E) {

cout«" Alokasi untuk PT gagal"«endl;

return 1;

// Mendealokasikan memori delete PT;

// Mendeklarasikan pointer yang akan menunjuk ke tipe in int *PI;

PI = new int;

*PI = 300;

cout«"\nNilai *PI : "«*pi«endl;

return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Operator new yang didefinisikan sendiri Nilai X : 2

Nilai Y : 5

Operator delete yang didefinisikan sendiri Nilai *PI: 300

Pemrograman C++

Berbeda dengan program sebelumnya, operator delete yang digunakan di sini adalah operator delete yang khusus kita definisikan sendiri untuk kelas TITIK. Sebagai bukti pernyataan ini, pada saat kita menggunakan operator delete terhadap pointer yang menunjuk ke kelas TITIK, maka di layar akan ditampilkan teks"Operator delete yang didefinisikan sendiri".

Sedangkan untuk penghapusan pointer PI yang menunjuk ke tipe int, operator delete yang digunakan masihlah operator asli yang terdapat pada C+ + .

Bab 14: Operator Overloading

(10)

Pemrograman C++

BAB 15

PREPROCESSOR DIRECTIVE

15.1 Pendahuluan

Dalam C+ + , kita dapat memasukkan berbagai macam perintah ke kompiler melalui preprocessor directive, yaitu perintah yang diawali dengan tanda pound (#). Meskipun perintah ini biasanya terdapat pada bagian awal program, namun sebenarnya kita dapat memasukkannya dimanapun (di dalam kode program) sesuai kebutuhan dari program yang akan kita buat. Perlu diperhatikan bahwa sebuah perintah yang menggunakan preprocessor directive harus diletakkan dalam satu baris tersendiri. Adapun beberapa directive yang terdapat dalam C + + adalah sebagai berikut:

#include #if ttifdef

#define

#pragma

#error

#elif

#else

#endif

#ifndef

#undef

#line

Bab 15: Prepocessor Directive

(11)

15.2 Directive # include

Directive #include digunakan untuk memasukkan file header ke dalam kode program yang kita tuliskan. Hal ini selalu kita lakukan pada setiap program C + + . Adapun caranya adalah dengan menuliskan file header yang akan dimasukkan setelah directive

#include. Sebagai contoh, jika kita akan memasukkan file header

<iostream> dan <cstdlib>, maka kita akan menuliskannya seperti berikut.

#include <iostream> HIMHjjjjHHlHHEi Jika kita telusuri lebih jauh, perintah di atas sebenarnya berfungsi untuk memasukkan kode-kode yang terdapat kedua file header tersebut ke dalam kode program kita. Artinya, sebelum mengeksekusi kode program, kompiler akan melakukan perintah- perintah yang terdapat pada preprocessor directive terlebih dahulu.

15.3 Directive ttdef ine

Kita dapat mendefinisikan sebuah makro identifier ke dalam sebuah program melalui directive #def ine. Prinsip dasar dari cara kerja

#define ini adalah menggantikan makro identifier tersebut dengan sebuah nilai yang kita definisikan di belakangnya. Sebagai contoh, kita ingin mendefinisikan sebuah makro identifier dengan nama TEST yang dikuti dengan nilai 10, maka kita akan menuliskannya seperti berikut. _^^^^_^^^^^^

tdefine TEST 10

Perintah tersebut menyebabkan setiap terdapat string TEST di dalam kode program, maka string tersebut akan digantikan oleh 10.

String yang dimaksud di sini tentunya bukanlah sebuah tipe data yang terdapat dalam C+ + . Berikut ini contoh implementasinya di dalam sebuah program.

Kode Program 15-1

ttinclude <iostream>

#define-TEST 10 using namespace std;

int main() {

// berarti hasil = (10 * 10) + 10 int hasil = (TEST * TEST) + TEST;

:;::COUt«"Hasilnya : "«hasil;

return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Hasilnya : 110

Untuk dapat lebih membuktikan pernyataan di atas, perhatikan kembali contoh program di bawah ini.

Kode Program 15-2 ttinclude <iostream>

tdef ine TEKS "Saya sangat menyukai C++"

using namespace std;

int main ( ) { COUt«TEKS;

return 0;

Pada program di atas perintah string TEKS akan digantikan oleh string "Saya sangat menyukai C++". Adapun hasil yang akan diberikan dari program di atas adalah sebagai berikut :

Saya sangat menyukai C+ +

Karena alasan inilah directive ttdefine juga sering digunakan dalam pendefinisian sebuah konstanta. Walaupun demikian, untuk mendefinisikan sebuah konstanta dalam C++ sebaiknya kita tetap menggunakan kata kunci const.

Pemrograman C++ Bab 15: Prepocessor Directive

(12)

15.4 Membuat Makro Fungsi dengan Directive ttdefine

Makro fungsi sebenarnya sama dengan sebuah fungsi bias a, hanya saja sebuah makro fungsi hanya terdiri dari satu baris perintah dan cara kerjanya sama dengan sebuah fungsi inline, yaitu melakukan penyalinan perintah yang terdapat pada baris tersebut ke dalam baris tertentu di dalam kode program. Pada bagian ini kita akan membahas pembuatan makro fungsi dengan menggunakan directive #define. Adapun contoh pendefinisiannya adalah seperti di bawah ini.

#define F ( x ) ( ( x * x ) + ( 2 * x ) + 1)

#define ABS(y) ( y ) < 0 ? - ( y ) : (y)

Berikut ini contoh program yang menunjukkan hal tersebut.

Kode Program 15-3

#include <iostream>

'/ Mendefinisikan fungsi F(x) = x2 + 2x + 1

^define F(x) ((x*x) + (2*x) + I)

V Mendefinisikan fungsi untuk menentukan harga mutlak / dari sebuah bilangan

^define ABS(y) (y)<0 ? -(y) : (y) ising namespace std;

int main() {

// Mendeklarasikan variabel a dan b yang bertipe int int a = 10, b = 5;

// Mendeklarasikan variabel c yang bertipe double double c = -4,56;

// Memanggil fungsi makro dan menampilkan hasilnya ke layar cout«"F("«a«") : "«F (a) «endl;

cout«"ABS ( "«b«") : U«ABS (b) «endl ; cout«"ABS("«c«") : "«ABS(c)«endl;

return 0; Mr . , .. '

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Pemrograman C++

F(10) ABS(5) ABS(-4.56)

121 5 4.56

Penting sekali untuk diperhatikan bahwa dalam penulisan sebuah makro fungsi, kita harus selalu menuliskan tanda kurung yang sesuai. Jika kita tidak (atau salah) menggunakan tanda kurung, maka hasil yang diperoleh dari makro fungsi tersebut juga akan salah. Sebagai contoh, berikut ini program yang menunjukkan pembuatan makro fungsi yang tidak menggunakan tanda kurung.

Kode Program 15-4

tinclude <iostream>

// Mendefinisikan fungsi untuk menghitung x tdefine F(x) x * x * x

using namespace std;

int main() { cout«F(5) ; return 0;

Hasil yang diberikan dari program di atas adalah sebagai berikut

125

Apa yang Anda lihat? Hasil yang diperoleh di atas memang masih benar, namun bagaimana jika pemanggilan fungsinya mengguna- kan sintaks berikut.

F (2+3) 4BBBB

Jika kita melakukan pemanggilan dengan cara seperti ini, m<

kompiler akan menerjemahkannya seperti berikut.

2 + 3 * 2 + 3 * 2 + 3 , : ; ' ; ' • ; ,,., • : :_ . . .^..^.'^

Karena operator * (perkalian) lebih tinggi tingkatannya dibandingkan operator + (penjumlahan), maka hasil perhitungan di atas adalah

2 + 6 + 6 + 3

Bab 15: Prepocessor Directive

(13)

Sehingga hasil akhir dari makro fungsi tersebut bukanlah 125, melainkan 17. Hal ini jelas salah dan tidak sesuai dengan apa yang kita harapkan. Untuk menghindari hal tersebut kita seharusnya menuliskan program di atas dengan sintaks seperti di bawah ini.

Kode Program 15-5

#include <iostream>

// Mendefinisikan fungsi untuk menghitung x3

#define F ( x ) (x) * (x) * (x) using namespace std?

int main{) { c o u t « F ( 5 ) ;

return 0; ^-B^.,,^.,^_

i * K

l

iHHHHRii!HHHHIHIIHHBHHHHB9^H

Dengan menggunakan cara ini, walaupun kita melakukan pemanggilan fungsi dengan F ( 2 + 3 ) , nilai yang dihasilkan akan tetap benar karena kompiler akan menerjemahkannya seperti berikut.

(2+3) V(2+3) '-*'• ( 2 + 3 )

Hal ini sama dengan

5 * 5 * 5

Sehingga nilai yang dihasilkan tetap benar, yaitu 125. Oleh karena itu dalam menuliskan sebuah makro fungsi, Anda harus teliti dan berhati-hati dalam menggunakan tanda kurung. Akan lebih baik lagi jika makro fungsi di atas dituliskan seperti berikut.

-:, -; •>• '^" r Seperti telah dijelaskan sebelumnya bahwa sebuah perintah preprocessor directive hanya ditampung dalam satu baris, namun jika kita ingin menuliskannya dalam dua baris atau lebih maka kita harus menggunakan tanda backslash (\) untuk menggabungkannya. Misalnya jika sebelumnya kita mempunyai perintah seperti berikut.

§

define F ( x ) ((x*x*x) + (2*x*x) + (x) +-1}

define TEKS "String ini terdapat pada makro'"identifier"':

Maka kita dapat menuliskannya seperti di bawah ini.

#define F ( x ) ((x*x*x) + \ (2*x*x) + \

Pemrograman

#define TEKS "String ini \

terdapat pada makro identifier'

15.5 Pemilihan dengan Menggunakan Directive

#if

Dalam C+ + , kita dapat melakukan suatu pemilihan dengan menggunakan preprocessor directive, diantaranya dengan menggunakan directive # i f . Setiap bentuk pemilihan yang menggunakan preprocessor directive selalu diakhiri dengan directive #endif. Bentuk umum penggunaannya adalah sama seperti pada saat kita melakukan pemilihan dengan struktur if, namun di sini kondisi yang akan diperiksa tidak harus dalam tanda kurung, sedangkan dalam struktur if hal tersebut merupakan suatu keharusan. Berikut ini bentuk umumnya.

Untuk satu buah kondisi

#if kondisi

Statemen__yang_akan__dilakukazif

#endif

Berikut ini contoh program yang merupakan implementasi dari pemilihan dengan menggunakan directive #if dengan satu kondisi.

#define X 200 using namespace std // Fungsi utama int main() {

// Melakukan pengecekan

#if X > 100

cout«x«" lebih besar dari

;;#endi f return 0;

Bab 15: Prepocessor Directive

(14)

Hasil yang akan diberikan dari program di atas adalah sebagai berikut :

200 lebih besar dari 100

Sedangkan untuk dua buah kondisi, kita harus menggunakan directive #else seperti yang terlihat pada bentuk umum di bawah

^^^^^^^^^^^^^^^^^

#if kondisi

Stat emen_yangr_akan__di 1 akukan_jika_kondi si_ terpenuhi /

false

Statemaa_yaaff_akan_dilakukan_Jika_kondi8i_tidak_terpen.'uhijr

#endif

Adapun contoh program yang menerapkan bentuk di atas adalah seperti yang tertulis di bawah ini.

using //

int //

#if X

#else cout

#endif return

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

80 lebih kecil dari 100

Seperti yang kita lihat dari hasil di atas, bahwa jika kondisi yang diperiksa tidak terpenuhi, maka program akan mengeksekusi statemen yang terdapat pada bagian directive #else.

Pemrograman C++

Terakhir, apabila kondisi yang akan diperiksa lebih dari dua, maka kita juga harus menggunakan directive #elif sehingga bentuk umumnya menjadi seperti di bawah ini.

#if kondisil ••••••••

Statemen.__yanff_akan_dilakukan_jika_kondisil_terpenuhi,'

#elif kondisi2

Statemen__yang_akan_dilakukan_jika_kondisi2_terpenuhi/

#elif kondisiN

Statemen_yang_akan_dilakukao_jika_koiidi8iN_terpenuhif

#else

Stat&men_lain_jika_kondi8il_saiapa.i_N_tidak_terpenuhit

#endi£

Berikut ini contoh program yang menunjukkan hal tersebut.

Kode Program 15-8

#include <iostream>

ttdefine X 100

using namespace std;

// Fungsi utama int main() {

// Melakukan pengecekan

#if X > 100

cout«X«" lebih besar dari 100";

felif X = 100

cout«" Nilai yang didefinisikan adalah 100";

ielse

cout«X«" lebih kecil dari 100";

tendif return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Nilai yang didefinisikan adalah 100

Mula-mula kompiler akan mengecek kondisi yang pertama (X >

100). Oleh karena kondisi tersebut tidak terpenuhi, selanjutnya

Bab 15: Prepocessor Directive

(15)

kompiler melakukan pengecekan terhadap kondisi kedua (X = 100). Karena kondisi ini terpenuhi, maka statemen yang terdapat di dalamnya akan dieksekusi (dalam hal ini yang terdapat pada directive # e l i f ) dan statemen yang terdapat pada directive

#else tentu akan diabaikan atau tidak dieksekusi.

15.6 Pemilihan dengan Menggunakan Directive ttifdef

Dalam C+ + , apabila kita akan melakukan suatu pengecekan sebuah makro, apakah makro tersebut sudah didefinisikan atau belum, maka kita dapat menggunakan directive # i f d e f (yang berarti #if defined). Sama halnya seperti directive # i f ,

# i f def juga harus diakhiri oleh directive #endif. Selain itu di sini juga memberlakukan penggunaan #else. Untuk lebih memperjelas hal tersebut, perhatikan program di bawah ini.

Kode Program 15-9

tinclude <iostream>

ttdefine X 200 using namespace std;

int main() {

// Melakukan pengecekan dengan directive #ifdef

#ifdef X

cout«"X telah didefinisikan"«endl;

#else

cout«"X belum didef inisikan"«endl ;

#endif return 0;

luta juga dapat menuliskan program di atas dengan sintaks seperti di bawah ini

Kode Program 15-10

#include <iostream>

#define X 200

using namespace std;

Pemrograman C++

// Melakukan pengecekan dengan #if defined

#if defined X

cout«"X telah didefinisikan"«endl;

#else

cout«"X belum didef inisikan"«endl;

tendif return 0;

Kedua program di atas akan menghasilkan keluaran sebagai berikut:

X telah didefinisikan

Sekarang jika terdapat program yang X-nya tidak didefinisikan terlebih dahulu, seperti pada program berikut.

Kode Program 15-11

#include <isotream>

using namespace std;

int main() {

// Melakukan pengecekan dengan iifdef

#ifdef X

cout«"X telah didefinisikan"«endl;

#else

cout«"X belum didefinisikan"«endl;

#endif return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

X belum didefinisikan

Seperti yang kita lihat bahwa pada prinsipnya pemilihan dengan menggunakan directive # i f d e f sama saja dengan pemilihan yang menggunakan directive # i f , artinya jika kondisi yang diperiksa tidak terpenuhi, maka statemen yang akan dilakukan adalah statemen yang terdapat pada bagian directive #else.

Bab 15: Prepocessor Directive

(16)

Sebenarnya tujuan dari pengecekan dengan directive # i f d e f ini adalah untuk mendefinisikan sebuah makro jika makro tersebut belum didefinisikan. Berikut ini contoh yang menunjukkan hal tersebut.

#include <iostream>

using namespace std;

int main() { ffifdef x

cout«"X telah didefinisikan"«endl

#else

cout«"Mendefinisikan X"«endl;

fdefine X 500 ttendif

cout«"X = "

return

> Wm

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Mendefinisikan X X = 500

15.7 Pemilihan dengan Menggunakan Directive ttifndef

Selain menggunakan directive #if dan # i f d e f , kita juga dapat melakukan pemilihan dengan directive ttifndef. #ifndef ini merupakan kebalikan dari # i f d e f . Berikut ini contoh program yang menunjukkan penggunaan directive #if ndef.

Pemrograman C++

lint main ( ) { j;'

] #ifndef X // bisa dituliskan dengan #if Idefln j cout«"X belum didef inisikan"«endl ;

j #else

j cout«"X telah .,d^tefinisikan"«endl;

j> #endif

I return 0;'«ySj

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

X belum didefinisikan

Seperti yang kita lihat bahwa jika makro identifier X belum didefinisikan, maka kondisi yang terdapat pada # i f n d e f X akan bernilai benar sehingga statemen yang akan dilakukan adalah statemen yang terdapat pada bagian ini, yaitu menampilkan teks

"X belum didefinisikan". Berikut ini contoh lain dari penggunaan directive #if ndef di dalam program.

Kode Program 15-14

tinclude <iostream>

using namespace std;

int m a i n ( ) { Mfndef X

cout«"X belum didefinisikan"«endl;

#define X 32 // Mendefinisikan X

cout«"Sekarang X telah didef inisikan"«endl;

#else

cout«"X telah didefinisikan"«endl,•

#endif

cout«"X = "«X«endl;

return 0;

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

X belum didefinisikan

Sekarang X telah didefinisikan X = 32

Bab 15: Prepocessor Directive

(17)

15.8 Directive tfunde f

Directive #undef berguna untuk menghapus makro yang telah didefinisikan sebelumnya. Ini berguna jika kita ingin melakukan perubahan nilai dari makro tersebut. Directive ini merupakan kebalikan dari directive #define. Berikut ini contoh program yang mengilustrasikan hal tersebut.

Kode Program 15-15

ttinclude <iostream>

ttdefine X 154 using namespace std;

int m a i n ( ) { cout«X«endl ; ttundef X eout«X«endl ;

// Menghapus definisi makro X // SALAH,karena definisi X sudah ti // ada lag!

return

Sebagai contoh lain, coba Anda perhatikan program di bawah ini.

Kode Program 15-16

ttinclude <iostream>

ttdefine X 154

using namespace std;

int main{) { ttifdef X

, cout«"X telah didefinisikan"«endl;

cout«"X = "«X«endl;

ttelse

cout«"X belum didefinisikan"«endl,•

ttendif

#undef X // Mengapus definisi makro

•fifndef X

Pemrograman C++

cout«"Sekarang X tidak didefinisikan lagi"«end

#else

cout«"X masih terdefinisi"«endl;

#endif return 0;

BBMBi

Hasil yang akan diberikan dari program di atas adalah sebagai berikut:

X telah didefinisikan X = 154

Sekarang X tidak didefinisikan lagi

15.9 Directive #error

Directive # err or digunakan untuk menghentikan proses kompilasi dan selanjutnya menampilkan pesan kesalahan. Biasanya, penggunaan directive ini berhubungan dengan directive # i f . Adapun bentuk umum dari penggunaannya adalah seperti di bawah ini.

#error pesan__kesalahan

Perlu diperhatikan bahwa pesan_kesalahan di atas tidak perlu diapit oleh tanda kutip dua ("") seperti halnya string yang biasa dituliskan di dalam C+ + . Berikut ini contoh program yang menunjukkan hal tersebut.

#include <iostream>

ttdefine X -10

using namespace std;

#if x == -10

tterror X tidak boleh bernilai negatif ttendif

Bab 15: Prepocessor Directive

(18)

Apabila program di atas dijalankan maka akan terjadi error yang ditampilkan oleh kompiler. Adapun pesan dari error tersebut adalah: X tidak boleh bernilai negatif.

Pemrograman C++

BAB 16

MENJEBAK ERROR

16.1 Pendahuluan

Dalam pembuatan sebuah program sering munciil error (kesalahan) dan bug, yang sering disebut dengan istilah eksepsi (exception).

Prioritas utama bagi seorang programmer yang berpengalaman adalah membuat program yang terbebas dari kesalahan pada saat runtime (waktu program dijalankan). Hal ini bukan merupakan hal yang mudah karena di sini kita harus pandai dalam menentukan kemungkinan-kemungkinan yang akan menyebabkan terjadinya error pada program kita. Setelah tahu apa yang mungkin menyebabkan terjadinya error, kemudian kita harus dapat mencegahnya sehingga meskipun hal itu terjadi, maka error tersebut tidak akan menghambat jalannya program. Proses seperti inilah yang disebut dengan penjebakan error atau yang lebih dikenal dengan istilah exception handling.

Pada bagian ini kita akan mempelajari bagaimana C + + dapat mencegah eksepsi-eksepsi yang terjadi. Walaupun demikian, perlu diperhatikan bahwa exception handling hanya terdapat pada kompiler C++ yang bahasanya telah memenuhi C + + standar.

Artinya jika Anda menggunakan kompiler C + + lama yang tidak mendukung exception handling, maka Anda tidak dapat melakukan kompilasi program yang terdapat pada latihan-latihan dalam bab ini.

Bab 16: Menjebak Error

(19)

16.2 Dasar-dasar Penjebakan Error

Untuk melakukan penjebakan error di dalam C+ + , terdapat tiga buah kata kunci yang akan digunakan yaitu try, catch dan throw. Konsep kerjanya sederhana, mula-mula program akan melakukan eksekusi terhadap satatemen-statemen yang terdapat pada blok try. Jika eksekusi berjalan baik (tidak terdapat error), maka statemen yang terdapat pada bagian catch akan diabaikan.

Namun jika terjadi error, maka error tersebut akan dilempar dengan statemen throw dan ditangkap dengan menggunakan statamen catch. Setelah ditangkap, maka error tersebut digantikan dengan statemen yang biasanya berupa sebuah pesan kesalahan. Statemen yang digunakan untuk menggantikan error yang terjadi ini disebut dengan istilah error handler.

Berikut ini bentuk umum dari penulisan sebuah blok yang dapat mencegah terjadinya error di dalam C + +.

try {

Statemen__yang_mungkin_menyebabkan_errorf

catch (tipe_data parameter) {

Statemen_yang_diguiiakaii__untuk_mengatasi_errorf

Statemen yang terdapat dalam blok try di atas dapat berupa statemen-statemen pendek atau dapat juga statemen-statemen yang telah didefinisikan dalam sebuah fungsi. Berikut ini contoh program yang akan mengilustrasikan cara kerja dari exception handling.

Kode Program 16-1

#include <iostream>

using namespace std;

int main' int X;

if (X <= 0) { throw X; , } else {

Pemrograman O

cout«"Nilai yang dimasukkan adalah "<1«Xj|

>y

fe

catch (int E) {

cout«"Program telah menangkap eksepsi yang bernilai cout«E;

Apabila program di atas dijalankan dan kita memasukkan nilai positif (lebih besar nol) maka contoh hasil yang akan diberikan dari program di atas adalah sebagai berikut:

Masukkan sebuah bilangan bulat positif : 10 Nilai yang dimasukkan adalah : 10

Hasil di atas merupakan hasil yang berjalan dengan baik tanpa adanya hal yang tidak diinginkan sehingga statemen yang terdapat pada bagian catch pun akan diabaikan. Namun apabila kita memasukkan nilai negatif, maka yang terjadi adalah seperti pada contoh hasil berikut

Masukkan sebuah bilangan bulat positif : -25

Program telah menangkap eksepsi dengan nilai: -25

Program di atas hanya akan menangkap eksepsi yang bertipe int saja, sedangkan jika kita akan melakukan penjebakan terhadap data yang bertipe lain, maka proses penangkapannya juga harus disesuaikan dengan tipe data yang dimasukkan. Sebagai contoh, kita akan melakukan penangkapan eksepsi dengan data bertipe double, maka kita harus menuliskannya seperti pada sintaks di bawah ini.

Kode Program 16-2

Mnclude <iostream>

using namespace std;

int m a i n ( ) { double X;

try {

Bab 16: Menjebak Error

(20)

cout«"Masukkan sebuah bilangan bulat positif : '

(double E]

Sekarang kita akan mencoba untuk rnelakukan penjebakan error yang statemen-statemennya telah didefinisikan di dalam sebuah fungsi. Berikut ini contoh programnya.

Kode Program 16-3

finclude <iostream>

using namespace std;

void BAGI(double X, double Y) { double HASIL;

I

if (Y != 0) { HASIL = X/Y;

cout«"Hasil bagi = "«HASIL?

} else { throw Y;

1

// Fungsi utama int main () {. ;

try {

cout« "Masukkan bilangan yang akan dibagi cin»a;

cout«"Masukkan bilangan pembagi cin»b;

cout«endl ;

Memanggil fungsi BAGI catch (doi

Pemrograman

,

return 0;cout«"

Pada program di atas, apabila kita memasukkan nilai variabel b yang lebih besar dari nol, maka program akan berjalan dengan baik tanpa adanya suatu error. Adapun contoh hasilnya adalah seperti berikut.

Masukkan bilangan yang akan dibagi Masukkan bilangan pembagi

Hasil bagi = 2.5

:7.5 :3.0

Namun jika variabel b bernilai nol, maka hal ini akan menimbulkan masalah di dalam program. Namun karena kita telah mendefinisikannya di dalam blok try. maka hal ini akan dicegah dengan rnelakukan eksekusi terhadap statemen yang terdapat pada bagian catch. Berikut ini hasil yang akan diberikan jika kita memasukkan nilai nol ke dalam variabel b.

Masukkan bilangan yang akan dibagi : 7.5 Masukkan bilangan pembagi : 0 Kesalahan : Terjadi pembagian dengan 0

16.3 Menjebak Banyak Error

C++ mengizinkan kita untuk dapat rnelakukan penjebakan error dari banyak tipe eksepsi. Hal ini sering disebut dengan multiple catch. Adapun bentuk umum dari penjebakan error yang melibatkan banyak tipe eksepsi adalah seperti terlihat di bawah ini.

try {

Statemen__yang_muiiffkin__menyebabkaii_error/

}

catch (tipe_datal parameter 1) {

Statemen_yang__digunakan_untuk_meagata8J._error/

Bab 16: Menjebak Error

(21)

catch (tipe_data2 parameters) {

Statemen_yang_diguxiakan_uatukjmengatasi_e

catch (tipe_dataN parameterN) {

Statemen_yang_<31gunakan_untukjaiengatasi_error/

Berikut ini contoh program yang menunjukkan hal tersebut.

tinclude <iostream>

using namespace std;

template <class T> void LEMPAR( T X) {

Scatch (int El) {

cout«"Menangkap eksepsi dengan tipe data int, yaitu :1 cout«El«endl ;

catch (double E2) {

cout«"Menangkap eksepsi dengan tipe data double, y^

cout«E2«endl ; }

catch (char E3) {

cout«"Menangkap eksepsi dengan tipe data char, yaitu : .;.- cout«E3«endl;

:1

[catch (char* E4) {

cout«"Menangkap eksepsi dengan tipe data char*, yaitu cout«E4«endl;

// Fungsi utama int main{) {

L E M P A R ( I O ) ; L E M P A R ( 2 5 . 0 3 ) ; L E M P A R (XC ' ) ; L E M P A R ( " C + + " ) ;

return 0;

Pemrograman

Jika Anda masih bingung dengan kehadiran kata kunci template di atas, coba Anda buka bab selanjutnya yang membahas tentang template. Namun, yang pasti program di atas akan memberikan hasil seperti berikut.

Menangkap eksepsi dengan tipe data int, yaitu : 10 Menangkap eksepsi dengan tipe data double, yaitu : 25.03 Menangkap eksepsi dengan tipe data char, yaitu : C Menangkap eksepsi dengan tipe data char*, yaitu : C + +

Hal di atas menunjukkan bahwa statemen catch akan menangkap eksepsi sesuai dengan tipe data yang didefinisikan. Sebagai bukti pernyataan ini, perhatikan kembali contoh program berikut.

ttinclude <iostream>

using namespace std;

template <class T> void LEMPAR(T X) { try {

if (X) { throw X;

catch (int El) {

cout«"Menangkap eksepsi dengan tipe data int, yaitu : cout«El«endl;

catch (double E2) {

cout« "Menangkap eksepsi dengan tipe data double, yait cout«E2«endl:

int main() {

LEMPAR("Mengungkap Rahasia C++");

return 0;

Pada program di atas kita hanya mendefinisikan statemen catch untuk menjebak eksepsi yang bertipe int dan double. Sedangkan nilai yang dilewatkan di dalam fungsi LEMPAR ( ) bertipe char*, yaitu "Mengungkap Rahasia C+ + ". Hal ini jelas akan

Bab 16: Menjebak Error

(22)

menimbulkan masalah dan program akan langsung dihentikan secara tidak normal. Penyebab dari munculnya masalah tersebut adalah karena kita tidak mendefinisikan statemen catch untuk tipe char*. Untuk itu, seharusnya kita tetap melakukan pencegahan eksepsi dari berbagai tipe data yang mungkin.

16.4 Menjebak Semua Jenis Error

Pada sub bab sebelumnya kita telah mempelajari bagaimana cara mendefinisikan statemen catch untuk menangkap tipe eksepsi yang spesifik. Namun di sana, kita masih harus mendefinisikannya untuk setiap tipe data. Sebenarnya, C + + telah menyediakan cara untuk menangkap semua tipe eksepsi, yaitu dengan mendefinisikannya dalam statemen catch yang mempunyai parameter . . . (titik tiga kali). Untuk lebih memperjelas, berikut ini bentuk umum dari penulisan sebuah blok try yang akan menangkap semua tipe eksepsi yang terjadi di dalam program.

try {

StatemeD_jyang_mungkiajmeayebabkaa._errorf }

catch (...) {

Statemen_jyang_digunakan_'untuk_meiigatasi_error/

Statemen catch ( . . . ) di atas menunjukkan bahwa program hanya mempunyai sebuah exception handler yang akan dibangkitkan ketika terjadi eksepsi dari tipe data apapun. Berikut ini contoh program yang akan mengilustrasikan hal tersebut.

Kode Program 16-6

#include <iostream>

using namespace std;

template <class T> void LEMPAR(T X]

try { if (X) {

throw X;

}

catch ( . . . ) {

cout«"Program menemukan sebuah kesalahan"«e

Pemrograman C++

// Fungsi utama iht m a i n ( ) {

LEMPAR(200);

LEMPAR(13.3);

LEMPAR('C') ;

LEMPAR("Mengungkap Rahasia C++

return 0;

Setiap tipe eksepsi yang dibangkitkan oleh program di atas melalui statemen throw, statemen catch akan menangkapnya dengan sebuah pesan yang sama, yaitu "Program menemukan sebuah kesalahan". Oleh karena pada fungsi main ( ) (fungsi utama) di atas terdapat empat pemanggilan fungsi LEMPAR ( ) , maka program di atas akan memberikan hasil seperti yang tampak di bawah ini.

Program menemukan sebuah kesalahan Program menemukan sebuah kesalahan Program menemukan sebuah kesalahan Program menemukan sebuah kesalahan

Apabila kita amati hasil program di atas, hanya terdapat satu statemen yang digunakan untuk mengatasi eksepsi, walaupun eksepsi di atas masing-masing bertipe int, double, char dan char*.

Perlu sekali untuk diperhatikan bahwa statemen catch ( . . . ) juga dapat digunakan berbarengan dengan statemen catch lainnya, asalkan penulisannya harus ada di posisi paling bawah.

Jika ditempatkan di atas atau di tengah-tengah, maka kompiler akan menampilkan kesalahan dan program tidak dapat dijalankan.

Sebagai contoh, di bawah ini adalah contoh program yang salah.

Kode Program 16-7

#include <iostream>

using namespace std;

template <class T> void LEMPAR(TX) {

•try {*JiIt':'

Bab 16: Menjebak Error

(23)

if (X) { throw X;

catch (...) {

cout«"Menangkap eksepsi dari tipe data lain"«endl;

catch (int El) {

cout«"Menangkap eksepsi dengan tipe data int, yaitu|

cout<<El«endl ,-

cout«E2«endl ;

Seharusnya program di atas dituliskan seperti berikut.

Kode Program 16-8

:atch (int El) {

cout« "Menangkap eksepsi dengan tipe data int, yaitu : ",- cout«El«endl;

catch (double E2) {

cout«"Menangkap eksepsi dengan tipe data double, yaitu cout«E2«endl ;

}

catch (...) {

Pemrograman C++

cout«"Menangkap eksepsi dari tipe data lain"«endl;

// Fungsi utama int main{) {

LEMPAR( ' C ' ) ; i LEMPAR(23);

LEMPAR(10.89};

LEMPAR("Penerbit INFORMATIKA Bandung");

return 0;

Pada program di atas kita hanya mendefinisikan statemen catch untuk tipe data int dan double saja sehingga jika terjadi eksepsi dari data lain (misalnya char atau char*) maka program akan menangkapnya dengan statemen yang terdapat pada bagian catch ( . . . ) . Berikut ini adalah hasil yang akan diberikan dari program di atas.

Menangkap eksepsi dari tipe data lain

Menangkap eksepsi dengan tipe data int, yaitu : 23 Menangkap eksepsi dengan tipe data double, yaitu : 10.89 Menangkap eksepsi dari tipe data lain

16.5 Menjebak Error yang Bertipe Kelas

Selain menangkap eksepsi yang berasal dari tipe data dasar, C+ + juga mengizinkan kita untuk menangkap eksepsi yang bertipe kelas. Justru pada prakteknya, program-program yang ditulis dengan C + + kebanyakan menggunakan eksepsi yang bertipe kelas.

Berikut ini contoh program yang mengilustrasikan hal di atas.

Kode Program 16-9

tinclude <iostream>

tinclude <cstring>

using namespace std;

// Membuat kelas eksepsi

Bab 16: Menjebak Error

(24)

class EKSEPSI { char* pesan;

public:

// Mendefinisikan fungsi EKSEPSI(char* S) {

strcpy(pesan, S);

V Mendefinisikan fungsi destructor -EKSEPSI() { delete pesan; }

// Mendefinisikan fungsi untuk mendapatkan nilai vari // pesan

char* GetPesanO { return pesan; }

// Fungsi utama int main() {

int X;

try {

cout« "Masukkan sebuah bilangan bulat negatif : "; cii cout«endl ;

if (X >= 0) {

throw EKSEPSI ("Nilai yang Anda masukkan bukc negatif");

} else {

cout«"Nilai yang Anda masukkan adalah : "«X;

Sedangkan apabila kita memasukkan nilai nol atau positif, maka contoh hasilnya akan tampak seperti berikut.

Seperti biasa, apabila kita memasukkan nilai sesuai yang diminta (yaitu nilai negatif) maka statemen yang terdapat pada bagian catch tidak akan dieksekusi. Namun, jika kita melakukan kesalahan yaitu dengan memasukkan nilai positif, maka program akan melemparkan eksepsi EKSEPSI dan menggantikannya dengan menampilkan pesan sesuai parameter yang terdapat dalam proses constructor-nya. Berikut ini contoh hasil dari program di atas apabila kita memasukkan nilai negatif.

Masukkan sebuah bilangan bulat negatif : -20 Nilai yang Anda masukkan adalah : -20

Masukkan sebuah bilangan bulat negatif : 100 Nilai yang Anda masukkan bukan negatif

16.6 Blok try Bersarang

Dalam C + + , kita diizinkan untuk membuat blok try bersarang.

Artinya di dalam blok try terdapat blok try lagi. Hal ini hanya dilakukan jika kita benar-benar membutuhkannya. Berikut ini contoh program yang menunjukkan hal tersebut.

Kode Program 16-10

#include <iostream>

using namespace std;

Pemrograman

//Fungsi utama

int main ( ) { MlH

.

int X; J^H jj&u&iiil^^^^B

• try { JB^B try { ||^^^^Bcout« "Masukkan sebuah bilangan bulat negatif :^^^^^^^^B c i n » X ; i^^^^^^li if (X > 0) { I^^^HIj throw X; i^^^^^^B

catch ( . . . ) { l^^E cout«"Menangkap eksepsi dalam blok try kedua"«enci^^^^B

} "WI^H

if (X) throw X; '^H

catch ( i n t E) { ^Hfli

cout«" Menangkap eksepsi dalam blok try pertama"«end]^^B

return 0; ,. N -if^l

xv-- • • '• - --:'-fe:3 MH

Hasil yang akan diberikan dari program di atas adalah sebagai berikut :

Bab 16: Menjebak Error

(25)

Masukkan sebuah bilangan bulat negatif : 100 Menangkap eksepsi dalam blok try kedua Menangkap eksepsi dalam blok try pertama

16.7 Mengenal Fungsi terminate ( ) dan unexpected()

Jika dalam program kita terjadi sebuah eksepsi dan program tidak menemukan exception handler yang sesuai, maka secara otomatis program akan memanggil fungsi terminate ( ) . Secara default, fungsi terminate ( ) ini sebenarnya memanggil fungsi yang lain, yaitu fungsi abort ( ) yang akan menyebabkan terhentinya program. Adapun prototipe dari fungsi ini sesuai dengan C+ + standar adalah seperti berikut. m,,m,r,,,,nr,,^^^

void terminate<),

Untuk lebih memahaminya, perhatikan program di bawah ini.

Kode Program 16-11

using namespace std;

int main() { int X;

try {

cout«"Masukkan sebuah bilangan bulat if (X) {

throw, X;

;ch (double El) {

cout«"Menangkap eksepsi dengan tipe double";

; catch (char E2) {

cout«"Menangkap eksepsi dengan tipe char";

}

catch (char* E3) {

"Menangkap eksepsi dengan tipe char*";

§

eturn 0;cout«

Pemrograman C++

Pada saat program di atas dijalankan dan kita memasukkan nilai maka program akan dihentikan secara tidak normal. Hal ini sebenarnya disebabkan karena kita tidak melempar eksepsi dengan tipe int, sedangkan kita hanya mendefinisikan statemen catch untuk tipe double, char dan char* saja sehingga eksepsi tersebut tidak dapat ditangkap. Oleh karena itu, program secara otomatis memanggil fungsi terminate ( ) sehingga program akan dihentikan.

Sedangkan fungsi unexpected() dipanggil pada saat terdapat statemen yang mencoba atau berusaha melempar sebuah eksepsi yang tidak boleh dilempar dengan menggunakan kata kunci throw. Secara default, fungsi unexpected ( ) ini akan memanggil fungsi terminate ( ) . Adapun prototipe dari fungsi ini adalah sebagai berikut.

void unexpected (,

16.8 Eksepsi Standar dalam C++

C + + telah menyediakan kelas-kelas eksepsi standar yang dapat langsung kita gunakan. Adapun beberapa yang termasuk ke dalamnya adalah seperti yang terlihat pada tabel di bawah ini.

Eksepsi

bad_alloc bad_cast bad_typeid bad_exception out_of_range invalid_argument overf low_error ios_base: : f a i l u r e

File header yang digunakan

<new>

<typeinf o>

<typeinf o>

<exception>

<stdexcept>

<stdexcept>

<stdexcept>

<ios>

Berikut ini gambar yang menunjukkan hirarki dari kelas eksepsi yang terdapat dalam C+ +.

Bab 16: Menjebak Error

(26)

exception

logic_error

length_error domain_error out_of_range invalid_argument

bad alloc bad_exception

runtime error

range_error overflow error underflow error

bad cast badjypeid

ios base-failure

BAB 17

TYPECASTING DAN RTTI

17.1 Pendahuluan

Typecasting adalah menganggap suatu variabel atau objek yang memiliki tipe tertentu dengan tipe data yang lain. Sebagai contoh, dalam program kita mempunyai variabel X yang bertipe int.

Namun suatu saat kita dapat menggunakan variabel tersebut sebagai tipe char. Di sini, berarti kita telah melakukan typecasting terhadap variabel X, yaitu dengan menganggap tipe int sebagai tipe char. Berikut ini bentuk umum untuk melakukan typecasting terhadap variabel atau objek tertentu dalam bahasa C.

tipe_data (nama_var label) / atau

ftipe_data; nama_variabel/

Namun dalam C + + , masih terdapat empat macam typecasting yang masing-masing mempunyai fungsi-fungsi spesifik. Adapun keempat macam itu adalah dynamic_cast, const_cast, static_cast dan reinterpret_cast.

Bab 17: Typecasting dan RTTI

Referensi

Dokumen terkait

Specifically, Mexican Ameri- cans have an increased incidence of intracerebral hemor- rhage and subarachnoid hemorrhage compared with non- Hispanic Whites adjusted for age, as well

Para santri menggunakan metode wahdah dengan cara (a) mempersiapkan al- Qur‟an pojok, (b) membaca satu persatu ayat-ayat yang hendak dihafalnya, dan (c) setiap ayat yang

Penelitian ini bertujuan untuk mengetahui besar penerimaan yang diperoleh dalam usaha keripik pisang gula aren pada industri Flamboyan kurun waktu 3 bulan,

Likuiditas ( liquidity ), profitabilitas ( profitability ), leverage, produktivitas ( productivity ), pertumbuhan perusahaan ( growth ), jaminan ( secure ), dan umur

Pengelolaan tanah berkaitan dengan manajemen kesuburan tanah yang diupayakan dengan cara penggunaan bahan organik (kompos) sebagai pupuk, diharapkan dapat

16-20 Januari 2006 Konsep Resiko Konsep Resiko Ancaman Kelemahan Dampak Tipe Resiko Tipe Resiko Model Model Proses Proses Kuantitatif Kualitatif TSI TSI Klasifikasi

Berangkat dari beberapa hal tersebut, maka permasalahan penelitian ini adalah sejauh mana kelembagaan pengelola KMN yaitu Pokja KMN dapat menjadi lembaga keuangan mikro di

Dari hasil inventarisasi yang dilaksanakan di Kabupaten Kepulauan Yapen, didapati bahwa pengelolaan sampah pada Tempat pembuangan Akhir Sampah (TPA) sampah Sarawandori di