Uncategorized

Tutorial Pemrograman Berorientasi Obyek dengan C++ : Template

Pada unit-unit praktikum sebelumnya telah disinggung sedikit mengenai overloading. Dengan overloading ini dapat diciptakan beberapa fungsi (untuk overloading terhadap fungsi) yang menangani sutu proses dengan tipe yang berlainan, tetapi dengan nama yang sama. Hal ini bertujuan untuk memudahkan dalam mengingat suatu fungsi. Seorang programmer cukup menggunakan nama fungsi yang sama untuk menyatakan operasi yang sama,walaupun tipe data berlainan. Tetapi walau cukup memudahkan, programmer juga tetap harus menuliskan kode untuk sejumlah fungsi walaupun dengan nama yang sama.

Untuk menyederhanakan penulisan kode pada masalah tersebut,C++ menyediakan suatu kemampuan yang disebut sebagai template. Dengan template ini, pemrogram dapat mengarahkan compiler agar membangkitkan kode fungsi pada berbagai tipe data secara otomatis.

Selain digunakan untuk membangkitkan fungsi, template juga dapat digunakan dalam kelas. Dalam hal ini template dipakai untuk mendeklarasikan anggota data dan juga fungsi-fungsi anggota kelas. Secara umum, format penulisannya adalah sebagai berikut :

Template <class T>
{
// tubuh fungsi
}

Bagian yang terletak di dalam tanda <> sesudah kata kunci template dapat berupa satu atau beberapa kata kunci class dan diikuti dengan pengenal template, misalnya :

<classA,classB>

Perintah program di atas menyatakan bahwa terdapat dua buah tipe data yang akan digunakan dalam template fungsi. Tanda koma bertindak sebagai pemisah nama kelas yang digunakan . Template juga dipakai untuk file-file header yang nanti akan diikutkan (include) dalam pembuatan program.

Berikut ini merupakan kode-kode program hasil praktikum yang merupakan salah satu contoh implementasi dari penggunaan template dalam Pemrograman Berorientasi Obyek. Sebuah template dalam bahasa C++ mempunyai ekstensi file “.h”. Oleh karena itu diperlukan dua buah file yaitu sebuah file berekstensi .h sebagai template dan file program utama yang berfungsi untuk menjalankan template tersebut. Program berikut ditulis dengan bahasa pemrograman C++:

// ganti.h
#include <vector>
#include <stdexcept>
template <typename T, typename CONT = std::vector<T> >
class Stack {
private:
CONT elems;		// elements
public:
void push (T const&);	//push element
void pop ();		//pop element
T top() const;		//return top element
bool empty() const {	//return whether the stack is
empty
return elems.empty;
}
};
template <typename T, typename CONT>
void Stack<T, CONT>::push (T const& elem)
{
elems.push_back(elem);	// append copy of passed elem
}
template <typename T, typename CONT>
void Stack <T, CONT>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop():empty stack");
}
elems.pop_back();	//remove last element
}
template <typename T, typename CONT>
T Stack <T, CONT>::top () const
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems.back();	//return copy of last element
}

Program di atas merupakan sebuah file yang disimpan dengan nama ganti.h. File ini merupakan file header yang dibuat sendiri oleh programmer untuk selanjutnya dapat digunakan oleh program utama yang membutuhkan file header ganti.h.

Untuk lebih jelasnya berikut merupakan uraian serta pembahasan tentang masing-masing baris program di atas yaitu sebagai berikut :

1. Semua baris yang diawali dengan dua buah tanda slash (//), akan dianggap sebagai baris komentar dan tidak akan berpengaruh pada hasil eksekusi program. Baris komentar dipakai oleh Programmer untuk memberikan penjelasan atau keterangan tentang maksud program tersebut. Bagian dari program di atas yang menggunakan dua buah tanda slash (//) yaitu :

   // ganti.h
...
...// elements
...
...	//push element
...		//pop element
...		//return top element
...	// return whether the stack is empty
...
...	// append copy of passed elem
...
...	//remove last element
...	//return copy of last element

2. Pernyataan yang diawali dengan tanda (#) merupakan pernyataan untuk menyertakan preprocessor. Pernyataan ini bukan untuk dieksekusi. Pernyataan seperti #include <vector> berarti memerintahkan kompiler untuk menyertakan file header vector yang merupakan Standard Template Library C++ yang mengimplementasikan 1-dimensional, random access sequence dari suatu item yang biasanya menggantikan array dimensi satu.  Kemudian juga terdapat fungsi #include <stdexcept> yang digunakan untuk exception handling. Bagian dari program di atas yang menggunakan tanda (#) yaitu :

  ...
#include <vector>
#include <stdexcept>
...

3. Pada program di atas terdapat sebuah kelas yang digunakan yaitu kelas Stack sbb :

template <typename T, typename CONT = std::vector<T> >
class Stack {
private:
CONT elems;		// elements
public:
void push (T const&);	//push element
void pop ();		//pop element
T top() const;		//return top element
bool empty() const {	// return whether the stack
is empty
return elems.empty;
}
};

Pernyataan baris program  di atas mengandung maksud bahwa dalam header ganti.h ini diciptakan suatu template dengan parameter T dan CONT. Parameter T berikutnya dapat ditentukan sendiri tipenya oleh user. CONT telah didefinisikan sejak awal yaitu sebagai vector, salah satu namespace dari std. Kelas yang digunakan adalah kelas Stack. Anggota kelas Stack yang bersifat privat adalah elems yang merupakan vector. Sedangkan anggota kelas yang bersifat public yaitu metode-metode kelas Stack. Metode-metode yang digunakan yaitu :

a. void push(T const&)

Metode push ini menggunakan parameter T (merupakan template). Tipe data T ini  ditentukan ketika pemanggilian metode, sehingga metode push ini dapat digunakan untuk berbagai tipe data sesuai keinginan programer, seperti misalnya int, float, char, array, dsb. Hal seperti inilah yang menjadi salah satu keuntungan penggunaan template. Sifat dari metode akan berbeda apabila tipe data yang digunakan berbeda. Parameter ini menggunakan data yang bersifat tetap (const) sehingga tidak dapat diubah. Prototype yang menggunakan tipe data void, berarti bahwa hasil eksekusinya tidak bertipe (tanpa parameter) dan tidak memberikan nilai balik.

b. void pop()

Metode pop ini tidak mempunyai nilai balik, karena mempunyai tipe data void.

c. T top() const

Metode top ini nilai baliknya menggunakan template T. Dengan menggunakan template tersebut maka nilai baliknya dapat ditentukan ketika pemanggilan metode.

d. bool empty() const

Metode ini akan memberikan nilai true apabila elems empty.

4. Berikut ini merupakan definisi metode push dalam kelas Stack :

template <typename T, typename CONT>
void Stack<T, CONT>::push (T const& elem)
{
elems.push_back(elem);// append copy of passed elem
}

Secara umum, baris program di atas mempunyai arti bahwa metode push berfungsi memasukkan data ke dalam stack pada urutan yang paling atas. Karena tipe manajemen datanya adalah stack, maka mekanisme push ini akan memasukkan data ke bagian paling atas dari stack kemudian mendorong data lama lebih dalam ke dalam stack. Baris template <typename T, typename CONT> menunjukkan pendefinisian template. Kemudian baris void Stack<T, CONT>::push (T const& elem) adalah baris pendefinisian metode push sebagai atribut dari kelas Stack. Baris fungsi elems.push_back(elem); berfungsi untuk melakukan operasi push_back() terhadap elems. Dengan operasi ini data baru dimasukkan ke dalam stack pada urutan yang paling atas.

5. Berikut ini merupakan definisi metode pop dalam kelas Stack :

template <typename T, typename CONT>
void Stack <T, CONT>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop():empty stack");
}
elems.pop_back();	//remove last element
}

Secara umum, baris program di atas mempunyai maksud bahwa metode pop berfungsi untuk mengeluarkan data dari stack. Data yang diambil adalah data yang berada di bagian paling atas dari kumpulan data stack, atau dapat dikatakan sebagai data yang terakhir kali masuk, kemudian menggeser data lama kembali ke atas.

Dalam pendefinisiannya, metode ini tidak banyak berbeda dengan metode sebelumnya. Perbedaanya hanya terdapat dalam isi metodenya. Isi dari metode ini akan menganalisis apakah stack dalam keadaan kosong atau tidak, jika kosong maka operasi pop tidak akan dilakukan, dan program akan menampilkan pesan “Stack<>::pop(): empty stack”. Fungsi yang digunakan untuk operasi pop adalah pop_back() yang berfungsi untuk mengeluarkan data teratas dari elems.

6. Berikut ini merupakan definisi metode top dalam kelas Stack :

template <typename T, typename CONT>
T Stack <T, CONT>::top () const
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems.back();	//return copy of last element
}

Secara garis besar, baris program di atas mempunyai maksud bahwa metode top digunakan untuk menampilkan data yang berada di urutan stack teratas, atau data yang paling terakhir masuk. Pada operasi ini tidak dilakukan pergeseran data. Dalam pendefinisian isi metode juga tidak banyak berbeda dengan sebelumnya, yang berbeda hanya isi dari metodenya. Metode ini juga akan melakukan pengecekan apakah stack dalam kondisi kosong atau tidak, kemudian secara otomatis akan mengembalikan nilai ke nilai elems.back(), yaitu elemen teratas dalam stack.

7. Tanda kurung kurawal ({…}) digunakan untuk menandai bagian suatu isi kelas dan bagian isi metode-metode di dalam kelas (behaviour).

8. Tanda titik koma (;) digunakan untuk menandai akhir penulisan data dan fungsi dalam program. Tanda titik koma tidak digunakan untuk mengakhiri nama kelas, nama metode, nama perubah akses, serta inisialisasi program utama.

Berikut ini merupakan kode-kode program utama yang digunakan untuk menjalankan file header ganti.h di atas. Kode program di bawah ini disimpan dalam bentuk file stack.cc.

//stack.cc
#include <iostream>
#include <deque>
#include <cstdlib>
#include "ganti.h"
int main()
{
Stack <int> intStack;
// stack of doubles which uses a std::deque<> to manage the elements
Stack<double, std::deque<double> > dblStack;
//manipulate int stack
intStack.push(7);
std::cout << intStack.top() << std::endl;
intStack.pop();
// manipulate double stack
dblStack.push(42.42);
std::cout << dblStack.top() << std::endl;
dblStack.pop();
dblStack.pop();
}

Untuk lebih jelasnya berikut merupakan uraian serta pembahasan tentang masing-masing baris program di atas yaitu sebagai berikut :

1. Semua baris yang diawali dengan dua buah tanda slash (//), akan dianggap sebagai baris komentar dan tidak akan mempengaruhi  hasil eksekusi program. Baris komentar dipakai oleh Programmer untuk memberikan penjelasan atau keterangan tentang maksud program tersebut. Bagian dari program di atas yang menggunakan dua buah tanda slash (//) yaitu :

//stack.cc
...
// stack of doubles which uses a std::deque<> to manage the elements
...
//manipulate int stack
...
// manipulate double stack
...

Pernyataan yang diawali dengan tanda (#) merupakan pernyataan untuk menyertakan preprocessor. Pernyataan ini bukan untuk dieksekusi. Misalnya dalam preprocessor #include <iostream> terdapat beberapa fungsi standar yang dipakai dalam proses input dan output. Contohnya yaitu perintah cout yang dipakai dalam program di atas merupakan bagian dari file header iostream.Demikian juga untuk preprocessor yang lain yang mempunyai library yang berbeda-beda. Bagian dari program di atas yang menggunakan tanda (#) yaitu :

...
#include <iostream>
#include <deque>
#include <cstdlib>
#include "ganti.h"
...

Pada bagian preprocessor directive tampak bahwa file ganti.h yang telah dibuat sebelumnya dideklarasikan dalam program ini. Hal ini akan menyebabkan program utama ini dapat mengakses template yang telah ditulis dalam file ganti.h.

3. Penulisan listing program untuk bagian program utama di atas selalu diawali dengan fungsi int main (). Fungsi dari program utama di atas yaitu untuk menentukan prosedur dan langkah eksekusi terhadap kelas-kelas yang telah dibuat, dalam hal ini kelas yang terdapat dalam template file header ganti.h. Berikut penjelasan untuk baris-baris program dalam main program di atas :

Stack <int> intStack;
// stack of doubles which uses a std::deque<> to manage the
elements
Stack<double, std::deque<double> > dblStack;

Di awal isi program utama di atas , terdapat pernyataan yang mendefinsikan dua buah obyek sebagai anggota dari kelas Stack (telah didefinisikan dalam file ganti.h). Tipe data yang digunakan dibedakan, yaitu menggunakan tipe data integer dan diberi nama intStack, sedangkan yang lain menggunakan tipe data double dan diberi nama dblStack. Kondisi ini menyebabkan perbedaan pada hasil eksekusi. Tipe data integer akan ditangani seperti operasi data integer dan tipe data double akan ditangani seperti operasi data double, sesuai dengan karakteristik tipe datanya.

Selanjutnya terdapat kode program seperti berikut :

…
//manipulate int stack
intStack.push(7);
std::cout << intStack.top() << std::endl;
intStack.pop();
...

Pernyataan di atas akan memerintahkan metode push kepada obyek intStack dengan melewatkan parameter bilangan integer sama dengan 7. Bilangan ini akan masuk ke dalam stack yang diberi nama intStack di urutan teratas. Kemudian dengan menggunakan fungsi cout (dari iostream.h) selanjutnya bilangan tersebut ditampilkan ke layar sebagai output dan ditampilkan isi teratas stack intStack dengan memerintahkan metode top. Lalu kemudian data dikeluarkan dari stack dengan fungsi pop.

…
//manipulate double stack
dblStack.push(42.42);
std::cout<<dblStack.top()<<std::endl;
dblStack.pop();
dblStack.pop();
…

Maksud pernyataan di atas hampir sama dengan kode program sebelumnya tetapi metode push diperintahkan kepada obyek dblStack dengan melewatkan parameter bilangan 42,42. Bilangan ini akan masuk ke dalam stack bernama dblStack pada urutan teratasnya. Kemudian dengan menggunakan fungsi cout (dari iostream.h) ditampilkan bilangan tersebut sebagai output dan ditampilkan isi teratas stack dblStack sesuai dengan metode top. Pada akhirnya data dikeluarkan dari stack dengan fungsi pop.

Secara keseluruhan, program ini menunjukkan bahwa untuk membut fungsi yang hampir sama untuk tipe data yang berbeda, dapat digunakan suatu template agar penulisan kode program tidak dilakukan secara berulang-ulang. Tipe data yang dimasukkan dalam fungsi tergantung sesuai dengan kebutuhannya.

4. Tanda kurung kurawal ({…}) digunakan untuk menandai bagian suatu isi kelas, bagian isi metode-metode di dalam kelas (behaviour), serta bagian isi program utama.

5. Tanda titik koma (;) digunakan untuk menandai akhir penulisan data dan fungsi dalam program. Tanda titik koma tidak digunakan untuk mengakhiri nama kelas, nama metode, nama perubah akses, serta inisialisasi program utama.

Setelah program utama tersebut disimpan, file program stack.cc selanjutnya dapat dipanggil untuk dilakukan eksekusi. Dalam praktikum ini, file tersebut dieksekusi dalam sistem operasi Unix dan dijalankan dengan console yang disediakan. Perintah yang digunakan beserta hasil eksekusinya tampak sebagai berikut :

praktikum@komputer07:~$ g++ stack.cc
praktikum@komputer07:~$ ./a.out
7
42.42
terminate called after throwing an instance of 'std::out_of_range'
what():  Stack<>::pop():empty stack
Aborted