Bab. 6 Template
Tujuan
Instruksional
|
|
·
Introduksi.
·
Template fungsi.
·
Template
overloading fungsi.
|
·
Template kelas.
·
Tipe default untuk
template kelas.
|
6.1 Introduksi
Pada bab ini, akan didiskusikan salah
satu fitur pendaur-ulangan C++ yang dikenal dengan template. Template fungsi
dan template kelas memampukan Anda untuk menspesifikasi, dengan segmen kode
tunggal, keseluruhan fungsi teroverload.
Hal ini dikenal dengan spesialisasi template fungsi. Konsep yang sama berlaku
untuk kelas yang dikenal dengan spesialisasi template kelas. Teknik ini dikenal
pula dengan pemrograman generik.
6.2 Template Fungsi
Fungsi-fungsi
teroverload normalnya melaksanakan
operasi yang identik atau yang mirip terhadap tipe-tipe data yang berbeda. Jika
operasi yang dilakukan identik untuk setiap tipe, maka hal itu dapat dilakukan
dengan lebih kompak menggunakan template fungsi. Pada awalnya, Anda menulis
sebuah definisi template fungsi tunggal. Berdasarkan tipe-tipe argumen yang
disediakan secara eksplisit dari pemanggilan terhadap fungsi ini, kompiler
membangkitkan fungsi-fungsi kode-sumber secara terpisah (yang dikenal dengan
spesialisasi template fungsi) untuk menangani setiap pemanggilan fungsi secara
tepat.
Semua
definisi template fungsi diawali dengan katakunci template yang diikuti dengan sebuah daftar parameter template
(diapit dengan kurung siku < >). Setiap parameter template yang
merepresentasikan sebuah tipe harus diawali dengan katakunci class atau typname, seperti
template< typename T >
atau
template< class TipeElemen >
atau
template< typename Tipe1, typename Tipe2 >
Parameter
template dari suatu definisi fungsi template digunakan untuk menspesifikasi
tipe parameter fungsi.
Contoh: Template
Fungsi TampilArray
Akan
diperiksa templat fungsi tampilArray
pada Gambar 6.1, baris 7-14. Template fungsi tampilArray mendeklarasikan (baris 7) suatu parameter template
tunggal T (T dapat berupa sembarang pengenal yang sah) untuk tipe array yang
akan ditampilkan oleh fungsi tampilArray; T dikenal sebagai parameter template
tipe atau parameter tipe.
Gambar 6.1 Menggunakan Spesialisasi Template Fungsi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// Gambar 6.1: gambar6_01.cpp
// Menggunakan spesialisasi template-fungsi.
#include <iostream>
using namespace std;
// definisi template fungsi tampilArray
template< typename T >
void tampilArray( const T * const array,
int hitung )
{
for ( int i = 0; i < hitung; ++i )
cout << array[ i ]<< "
";
cout << endl;
} // akhir dari template fungsi tampilArray
int main()
{
const int aHitung = 5; // ukuran
array a
const int bHitung = 7; // ukuran
array b
const int cHitung = 6; // ukuran
array c
int a[ aHitung ] = { 1, 2, 3, 4, 5 };
double b[ bHitung ] = { 1.1, 2.2,
3.3, 4.4, 5.5, 6.6, 7.7 };
char c[ cHitung ] =
"HALLO"; // posisi ke-6 untuk null
cout << "Array a memuat:"
<< endl;
//
memanggil spesialisasi template fungsi integer
tampilArray( a, aHitung );
cout << "Array b memuat:"
<< endl;
//
memanggil spesialisasi template fungsi double
tampilArray( b, bHitung );
cout << "Array c memuat:"
<< endl;
//
memanggil spesialisasi template fungsi karakter
tampilArray( c, cHitung );
} //
akhir dari main
|
Array a memuat:
1 2 3 4 5
Array b memuat:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
Array c memuat:
HALLO
Ketika
kompiler mendeteksi pemanggilan fungsi tampilArray
di dalam program klien (baris 29 dan 34), kompiler menggunakan kapabilitas
teroverloadnya untuk menemukan definisi fungsi tampilArray yang paling cocok dengan pemanggilan fungsi tersebut.
Perhatikan pemanggilan fungsi pada baris 29. Kompiler membandingkan tipe
argumen pertama pada tampilArray (int * pada baris 29) dengan parameter
pertama template fungsi tampilArray (const T * const pada baris 8) dan menyimpulkan bahwa penggantian parameter
tipe T dengan int akan membuat
argumen konsisten dengan parameter tersebut. Kemudian, kompiler mengganti int
untuk T pada definisi template dan mengkompilasi spesialisasi tampilArray yang dapat menampilkan
sebuah array yang memuat nilai-nilai int.
Pada Gambar 6.1, kompiler menciptakan dua spesialisasi tampilArray, yaitu satu yang mengharapkan sebuah array int dan satu lagi yang mengharapkan
sebuah array double. Sebagai contoh,
spesialisasi template fungsi untuk tipe int
adalah:
void tampilArray( const int * const array, int hitung )
{
for ( int i = 0; i < hitung; ++i )
cout << array[ i ]
<< " ";
cout << endl;
} // akhir dari fungsi tampilArray
Sama
seperti parameter fungsi, nama parameter template harus unik di dalam sebuah
definisi template. Nama parameter template tidak harus unik antar template
fungsi yang berbeda.
Gambar
6.1 mendemonstrasikan template fungsi tampilArray
(baris 7-14). Program memulainya dengan mendeklarasikan suatu array
berelemen-lima int, a, dan suatu array berelemen-tujuh double, b (baris 22-23). Kemudian, program menampilkan setiap array dengan
memanggil tampilArray, sekali dengan
argumen pertama a bertipe int *
(baris 29) dan sekali lagi dengan argumen pertama b bertipe double * (baris 34). Pemanggilan pada
baris 29, misalnya, menyebabkan kompiler menyimpulkan bahwa T adalah int. Pemanggilan pada baris 34
menyebabkan kompiler menyimpulkan bahwa T adalah double dan menginstasiasi spesialisasi template fungsi tampilArray yang kedua. Penting untuk
mencatat bahwa jika T (baris 7) merepresentasikan suatu tipe yang didefinisikan
sendiri oleh pengguna (bukan kasus pada Gambar 6.1), maka harus ada suatu
operator penyisipan aliran (stream) teroverload untuk tipe tersebut; jika
tidak, operator penyisipan stream pertama pada baris 11 tidak akan bisa
dikompilasi.
Pada
contoh ini, mekanisme template menghemat waktu Anda dari keharusan untuk
menuliskan dua fungsi teroverload
yang terpisah dengan prototipe
void tampilArray( const int * const, int );
void tampilArray (
const double * const, int );
void tampilArray ( const char * const, int );
6.3 Mengoverload Template Fungsi
Template
fungsi dan overloading keduanya
saling terkait. Spesialisasi template fungsi dibangkitkan dari suatu template
fungsi yang semuanya memiliki nama sama, sehingga kompiler menggunakan resolusi
overload untuk memanggil fungsi yang
cocok.
Template
fungsi dapat dioverload dalam beberapa
cara. Anda bisa menyediakan beberapa template fungsi yang menspesifikasi nama
fungsi sama tetapi dengan parameter fungsi yang berbeda. Sebagai contoh,
template fungsi tampilArray pada
Gambar 6.1 dapat dioverload dengan
template fungsi tampilArray dengan
dua parameter tambahan subskriptBawah
dan subskriptAtas untuk
menspesifikasi sepenggal aray yang akan ditampilkan.
Template
fungsi dapat pula dioverload dengan
menyediakan beberapa fungsi non-template dengan nama sama tetapi dengan argumen
fungsi yang berbeda. Sebagai contoh, template fungsi tampilArray pada Gambar 6.1 dapat dioverload dengan suatu versi non-template yang secara khusus
menampilkan sebuah array karakter dalam format tabular.
Kompiler
melakukan proses pencocokan untuk menentukan fungsi apa yang akan dipanggil
ketika sebuah fungsi dipanggil. Pertama-tama, kompiler mencoba untuk menemukan
dan menggunakan pencocokan presisi dimana di dalamnya nama fungsi dan tipe
argumen konsisten dengan yang ada pada pemanggilan fungsi. Jika ini gagal,
kompiler menentukan apakah suatu template fungsi tersedia atau tidak yang dapat
dipakai untuk membangkitkan spesialisasi template fungsi dengan pencocokan presisi
(dengan nama fungsi dan tipe argumen konsisiten dengan yang ada pada
pemanggilan fungsi). Jika template semacam itu ditemukan, maka kompiler akan
membangkitkan spesialisasi template fungsi yang sesuai. Jika tidak ditemukan,
kompiler akan mengeluarkan pesan error. Juga, jika terdapat kecocokan lebih
dari satu untuk pemanggilan fungsi, kompiler akan mencoba menentukan kecocokan
terbaik. Jika terdapat lebih dari satu kecocokan terbaik, maka pemanggilan
tersebut akan dipandang ambigu dan kompiler akan mengeluarkan pesan error.
6.3 Mengoverload Template Fungsi
Adalah
hal yang mungkin untuk memahami konsep stack
atau tumpukan (suatu struktur data dimana Anda bisa menyisipkan item ke atas
tumpukan dan mengambil item dengan urutan last-in, first-out) yang independen dari tipe item yang
sedang ditempatkan di dalam tumpukan. Namun, untuk menginstansiasi suatu
tumpukan, tipe data harus dispesifikasi. Hal ini menciptakan kesempatan untuk
pendaur-ulangan kode. Anda membutuhkan cara dalam menjelaskan tumpukan secara
generik dan menginstansiasi kelas dengan versi kelas tumpukan generik bertipe
spesifik. C++ menyediakan kapabilitas ini lewat template kelas.
Template
kelas disebut dengan tipe terparameterisasi, karena memerlukan satu atau lebih
parameter tipe untuk menspesifikasi bagaimana merealisasikan spesialisasi
template kelas. Untuk menghasilkan banyak spesialisasi, Anda hanya menulis satu
definisi template kelas. Ketika sebuah spesialisasi tambahan diperlukan, Anda
hanya perlu memakai notasi singkat dan sederhana dan kompiler akan menuliskan
kode sumber spesialisasi itu untuk Anda. Satu template kelas Tumpukan, misalnya, dapat menjadi basis
dalam menciptakan kelas Tumpukan
lainnya (seperti Tumpukan dari double, Tumpukan dari int, Tumpukan dari char, Tumpukan dari Pegawai, dan lainnya).
Menciptakan
Template Kelas Tumpukan<T>
Perhatikan
definisi template kelas Tumpukan pada Gambar 6.2. Tampak bahwa definisi itu
seperti definisi kelas konvensional, kecuali bahwa ia diawali dengan header
(baris 6)
template< typename T >
untuk
menspesifikasi definisi template kelas dengan parameter tipe T, yang berperan
sebagai placeholder untuk tipe kelas Tumpukan
yang akan diciptakan. Anda tidak perlu harus menggunakan pengenal T, karena
sembarang pengenal yang valid bisa digunakan. Tipe elemen yang akan disimpan
pada Tumpukan ini disebutkan secara
generik sebagai T pada header kelas Tumpukan
dan definisi-definisi fungsi anggota. Anda akan melihat bagaimana T menjadi
sebuah tipe spesifik, seperti double
atau int. Karena cara perancangan
template kelas ini, ada dua pembatasan untuk tipe kelas yang bisa digunakan
dengan Tumpukan ini. Pembatasan
pertama adalah keharusan memiliki konstruktor default (digunakan pada baris 44
untuk menciptakan array yang menyimpan elemen-elemen tumpukan). Pembatasan
kedua adalah bahwa operator penugasan harus menyalin objek secara benar ke Tumpukan (baris 56 dan 70).
Gambar 6.2 Template Kelas Tumpukan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
// Gambar 6.2: Tumpukan.h
// Template kelas Tumpukan.
#ifndef TUMPUKAN_H
#define TUMPUKAN_H
template< typename T >
class Tumpukan
{
public:
explicit
Tumpukan( int = 10 ); // konstruktor
default (ukuran Tumpukan 10)
// destruktor
~Tumpukan()
{
delete [] tumpukanPtr; // membebaskan memori internal untuk Tumpukan
} // akhir dari destruktor ~Tumpukan
bool push( const T & ); // mendorong elemen ke atas Tumpukan
bool pop(T &); // membuang sebuah elemen dari
Tumpukan
//
menentukan apakah Tumpukan kosong
bool apaKosong() const
{
return atas == -1;
} // akhir dari fungsi apaKosong
// menentukan apakah Tumpukan penuh
bool apaPenuh() const
{
return atas == ukuran - 1;
} // akhir dari fungsi apaPenuh
private:
int
ukuran; // # jumlah elemen di dalam Tumpukan
int atas; // lokasi elemen teratas
(-1 berarti Tumpukan kosong)
T *tumpukanPtr; // pointer ke
representasi internal dari Tumpukan
}; // akhir dari kelas Tumpukan
//
template konstruktor
template< typename T >
Tumpukan<
T >::Tumpukan( int s )
: ukuran( s > 0 ? s : 10 ), //
memvalidasi ukuran
atas( -1 ), // Tumpukan awalnya kosong
tumpukanPtr( new T[
ukuran ] ) // mengaloksikan memori untuk elemen-elemen
{
// tubuh kosong
} // akhir dari template konstruktor
Tumpukan
// mendorong elemen ke atas Tumpukan;
// jika berhasil, menghasilkan true;
sebaliknya, menghasilkan false
template< typename T >
bool Tumpukan< T >::push( const T
&nilaiPush )
{
if ( !apaPenuh() )
{
tumpukanPtr[ ++atas ] = nilaiPush; //
menempatkan item pada Tumpukan
return true; // push
berhasil
} // akhir dari if
return false; // push gagal
} // akhir dari template fungsi push
// membuang elemen dari Tumpukan;
// jika berhasil, menghasilkan true;
sebaliknya, menghasilkan false
template< typename T >
bool Tumpukan< T >::pop( T &nilaiPop )
{
if ( !apaKosong() )
{
nilaiPop = tumpukanPtr[ atas-- ]; //
menghapus item dari Tumpukan
return true; // pop berhasil
} // akhir dari if
return false; // pop gagal
} // akhir dari template fungsi pop
#endif
|
Definisi
fungsi anggota dari suatu template kelas merupakan template fungsi. Definisi
fungsi anggota yang berada di luar definisi template kelas diawali dengan
header
template< typename T >
(baris
40, 51, dan 65). Jadi, setiap definisi menyerupai definisi fungsi, kecuali
bahwa tipe elemen Tumpukan selalu
dicantumkan secara generik sebagai parameter tipe T. Operator resolusi skop
digunakan dengan nama template kelas Tumpukan<T>
(baris 41, 52, dan 66) untuk mengikat setiap definisi fungsi anggota kepada
skop template kelas. Pada kasus ini, nama kelas generik adalah Tumpukan<T>. Ketika doubleTumpukan diinstansiasi sebagai
tipe Tumpukan<double>, spesialisasi template fungsi konstruktor Tumpukan menggunakan new untuk menciptakan sebuah array yang
memuat elemen-elemen bertipe double
untuk merepresentasikan tumpukan (baris 44). Statemen
tumpukanPtr( new T[ ukuran ] );
di
dalam definisi template kelas Tumpukan
dibangkitkan oleh kompiler di dalam spesialisasi template kelas Tumpukan<double> sebagai
tumpukanPtr( new double[ ukuran ] );
Menguji Template
Kelas Tumpukan<T>
Sekarang
akan dilakukan pengujian template kelas Tumpukan
(Gambar 6.3). Pengujian diawali dengan menginstansiasi objek doubleTumpukan berukuran 5 (baris 9).
Objek ini dideklarasikan sebagai objek dari kelas Tumpukan<double>.
Kompiler mengasosiasikan tipe double
dengan parameter tipe T di dalam template kelas untuk menghasilkan kode sumber
untuk kelas Tumpukan bertipe double. Template menawarkan keuntungan
pendaur-ulangan kode, karena spesialisasi-spesialisasi template kelas diinstansiasi
di dalam suatu program (pada waktu kompilasi).
Gambar 6.3 Menguji Template Kelas Tumpukan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
// Gambar 6.3: gambar6_03.cpp
// Program menguji template kelas Tumpukan.
#include <iostream>
#include "Tumpukan.h" // definisi
template kelas Tumpukan
using namespace std;
int main()
{
Tumpukan< double > doubleTumpukan( 5 ); // ukuran 5
double doubleNilai = 1.1;
cout << "Mendorong
elemen-elemen ke atas doubleTumpukan\n";
// mendorong 5 double ke atas doubleTumpukan
while( doubleTumpukan.push( doubleNilai ) )
{
cout << doubleNilai << ' ';
doubleNilai += 1.1;
} // akhir dari while
cout << "\nTumpukan penuh.
Tidak bisa push " << doubleNilai
<< "\n\nMembuang
elemen-elemen dari doubleTumpukan\n";
// mengambil elemen-elemen dari
doubleTumpukan
while( doubleTumpukan.pop( doubleNilai ) )
cout << doubleNilai << ' ';
cout << "\nTumpukan kosong.
Tidak bisa pop\n";
Tumpukan< int >
intTumpukan; // ukuran default 10
int intNilai = 1;
cout << "\nMendorong
elemen-elemen ke atas intTumpukan\n";
// mendorong 10 integer ke atas intTumpukan
while( intTumpukan.push( intNilai ) )
{
cout << intNilai++ << ' ';
} // akhir dari while
cout << "\nTumpukan penuh.
Tidak bisa push " << intNilai
<< "\n\nMembuang
elemen-elemen dari intTumpukan\n";
// membuang elemen-elemen dari intTumpukan
while( intTumpukan.pop( intNilai ) )
cout << intNilai << ' ';
cout << "\nTumpukan kosong. Tidak
bisa pop" << endl;
} // akhir dari main
|
Mendorong elemen-elemen ke atas doubleTumpukan
1.1 2.2 3.3 4.4 5.5
Tumpukan penuh. Tidak bisa push 6.6
Membuang elemen-elemen dari doubleTumpukan
5.5 4.4 3.3 2.2 1.1
Tumpukan kosong. Tidak bisa pop
Mendorong elemen-elemen ke atas intTumpukan
1 2 3 4 5 6 7 8 9 10
Tumpukan penuh. Tidak bisa push 11
Membuang elemen-elemen dari intTumpukan
10 9 8 7 6 5 4 3 2 1
Tumpukan kosong. Tidak bisa pop
Baris
15-19 memanggil push untuk
menempatkan nilai-nilai double 1.1,
2.2, 3.3, 4.4, dan 5.5 ke atas doubleTumpukan.
Loop while berhenti jika program
mencoba untuk menempatkan nilai keenam ke atas doubleTumpukan (yang telah penuh, karena hanya mampu menampung lima
elemen). Fungsi push menghasilkan false ketika tidak bisa menempatkan
sebuah nilai ke atas tumpukan.
Baris
25-26 memanggil pop di dalam sebuah
loop while untuk menghapus lima
elemen dari tumpukan (perhatikan bahwa keluaran pada Gambar 6.3 menunjukkan
nilai-nilai dibuang atau dihapus dalam urutan last-in, first-out). Ketika program mencoba untuk menghapus nilai keenam, doubleTumpukan sudah kosong, sehingga
loop berhenti. Baris 30 menginstansiasi tumpukan integer intTumpukan dengan deklarasi
Tumpukan< int > intTumpukan;
Karena
tidak ada ukuran yang dispesifikasi, ukuran default berlaku (10) seperti yang
dispesifikasi di dalam konstruktor default (Gambar 6.2, baris 10). Baris 35-38
beriterasi dan memanggil push untuk
menempatkan nilai-nilai int ke atas intTumpukan sampai penuh, kemudian baris
44-45 beriterasi dan memanggil pop
untuk membuang nilai-nilai int dari intTumpukan sampai kosong. (perhatikan
juga bahwa keluaran pada Gambar 6.3 menunjukkan nilai-nilai dibuang atau
dihapus dalam urutan last-in, first-out).
Menciptakan
Template Fungsi untuk Menguji Template Kelas Tumpukan<T>
Perhatikan
bahwa kode di dalam fungsi main pada
Gambar 6.3 hampir identik dengan kedua manipulasi doubleTumpukan pada baris 9-28 dan manipulasi intTumpukan pada baris 30-47. Hal ini menyediakan kesempatan lain
untuk menggunakan sebuah template fungsi. Gambar 6.4 mendefinisikan template
fungsi ujiTumpukan (baris 10-34)
untuk melakukan tugas yang sama dengan fungsi main pada Gambar 6.3, yaitu mendorong (push) sederet nilai ke atas Tumpukan<T>
dan membuang (pop) sederet nilai dari
Tumpukan<T>.
Template
fungsi intTumpukan menggunakan
parameter template T (dispesifikasi pada baris 10) untuk merepresentasikan tipe
data yang disimpan di dalam Tumpukan<T>.
Template fungsi mengambil empat argumen (baris 12-15), yaitu suatu referensi
yang menunjuk ke sebuah objek bertipe Tumpukan<T>,
sebuah nilai bertipe T yang akan menjadi nilai pertama yang akan ditempatkan ke
atas Tumpukan<T>, sebuah nilai bertipe
T yang digunakan untuk menginkremen nilai-nilai yang ditempatkan ke atas Tumpukan<T>, dan sebuah string
yang merepresentasikan nama objek Tumpukan<T>
untuk ditampilkan pada keluaran.
Fungsi
main (baris 36-43) menginstansiasi
sebuah objek bertipe Tumpukan<double> yang dinamakan doubleTumpukan (baris 38) dan sebuah
objek bertipe Tumpukan<int> yang dinamakan intTumpukan (baris 39). Fungsi main menggunakan kedua objek tersebut
pada baris 41 dan 42. Kompiler menyimpulkan tipe T untuk ujiTumpukan dari tipe yang digunakan untuk menginstansiasi argumen
pertama fungsi (tipe yang digunakan untuk menginstansiasi doubleTumpukan atau intTumpukan).
Keluaran dari Gambar 6.4 identik dengan keluaran dari Gambar 6.3.
Gambar 6.3 Menguji Template Kelas Tumpukan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
// Gambar 6.4: gambar6_04.cpp
// Program menguji
template kelas Tumpukan. Fungsi main menggunakan sebuah
// template fungsi
untuk memanipulasi objek-objek bertipe Tumpukan<T>.
#include <iostream>
#include <string>
#include "Tumpukan.h" // definisi
template kelas Tumpukan
using namespace std;
// template fungsi untuk memanipulasi
Tumpukan<T>
template< typename T >
void ujiTumpukan(
Tumpukan<
T > &Tumpukan2, // referensi ke Tumpukan< T >
T
nilai, // nilai awal yang akan ditempatkan ke atas tumpukan
T
inkremen, // menginkremen nilai-nilai
const
string namaTumpukan ) // nama objek Tumpukan<T>
{
cout
<< "\nMendorong elemen-elemen ke atas " <<
namaTumpukan << '\n';
//
mendorong elemen-elemen ke atas Tumpukan
while
( Tumpukan2.push( nilai ) )
{
cout
<< nilai << ' ';
nilai
+= inkremen;
} //
akhir dari while
cout
<< "\nTumpukan penuh. Tidak bisa push " << nilai
<<
"\n\nMembuang elemen-elemen dari " << namaTumpukan
<< '\n';
//
membuang elemen-elemen dari Tumpukan
while
( Tumpukan2.pop( nilai ) )
cout
<< nilai << ' ';
cout
<< "\nTumpukan kosong. Tidak bisa pop" << endl;
} // akhir dari template fungsi ujiTumpukan
int main()
{
Tumpukan< double >
doubleTumpukan( 5 ); // ukuran 5
Tumpukan< int > intTumpukan; //
ukuran default 10
ujiTumpukan(
doubleTumpukan, 1.1, 1.1, "doubleTumpukan" );
ujiTumpukan(
intTumpukan, 1, 1, "intTumpukan" );
} // akhir dari main
|
Mendorong elemen-elemen ke atas doubleTumpukan
1.1 2.2 3.3 4.4 5.5
Tumpukan penuh. Tidak bisa push 6.6
Membuang elemen-elemen dari doubleTumpukan
5.5 4.4 3.3 2.2 1.1
Tumpukan kosong. Tidak bisa pop
Mendorong elemen-elemen ke atas intTumpukan
1 2 3 4 5 6 7 8 9 10
Tumpukan penuh. Tidak bisa push 11
Membuang elemen-elemen dari intTumpukan
10 9 8 7 6 5 4 3 2 1
Tumpukan kosong. Tidak bisa pop
Kesimpulan
Semua definisi template fungsi
diawali dengan katakunci template
yang diikuti dengan sebuah daftar parameter template (diapit dengan kurung siku
< >). Setiap parameter template yang merepresentasikan sebuah tipe harus
diawali dengan katakunci class atau typname.
Template fungsi dan overloading keduanya saling terkait.
Spesialisasi template fungsi dibangkitkan dari suatu template fungsi yang
semuanya memiliki nama sama, sehingga kompiler menggunakan resolusi overload untuk memanggil fungsi yang
cocok.
Kompiler melakukan proses
pencocokan untuk menentukan fungsi apa yang akan dipanggil ketika sebuah fungsi
dipanggil. Pertama-tama, kompiler mencoba untuk menemukan dan menggunakan
pencocokan presisi dimana di dalamnya nama fungsi dan tipe argumen konsisten
dengan yang ada pada pemanggilan fungsi. Jika ini gagal, kompiler menentukan
apakah suatu template fungsi tersedia atau tidak yang dapat dipakai untuk membangkitkan
spesialisasi template fungsi dengan pencocokan presisi (dengan nama fungsi dan
tipe argumen konsisiten dengan yang ada pada pemanggilan fungsi). Jika template
semacam itu ditemukan, maka kompiler akan membangkitkan spesialisasi template
fungsi yang sesuai. Jika tidak ditemukan, kompiler akan mengeluarkan pesan
error. Juga, jika terdapat kecocokan lebih dari satu untuk pemanggilan fungsi,
kompiler akan mencoba menentukan kecocokan terbaik. Jika terdapat lebih dari
satu kecocokan terbaik, maka pemanggilan tersebut akan dipandang ambigu dan
kompiler akan mengeluarkan pesan error.
Latihan
1)
Lakukan overload terhadap template fungsi tampilArray pada Gambar 6.1 sehingga fungsi itu mengambil dua
argumen integer tambahan, int
bawahSubskript dan int atasSubskript.
Pemanggilan terhadap fungsi ini hanya
akan menampilkan sepenggal array yang ditentukan oleh batas bawahSubskript dan atasSubskript. Validasilah bawahSubskript
dan atasSubskript jika terletak di
luar rentang array atau jika atasSubskript
kurang dari atau sama dengan bawahSubskript,
maka tampilArray akan memberikan nilai balik 0. Kemudian modifikasi main untuk menguji kedua versi tampilArray pada array a, b,
dan c.
2)
Tulislah sebuah template fungsi
sederhana untuk fungsi predikat apaSamaDengan
yang membandingkan kedua argumennya yang bertipe sama menggunakan operator
ekualitas (==). Fungsi ini menghasilkan true
jika kedua argumen sama dan mengembalikan false
jika tidak sama. Gunakan template fungsi ini di dalam sebuah program yang
memanggil apaSamaDengan hanya untuk
tipe-tipe integral. Kemudian tulislah sebuah program terpisah yang memanggil apaSamaDengan untuk tipe yang
didefinisikan pengguna, tanpa perlu mengoverload
operator ekualitas. Apakah yang terjadi jika Anda mencoba menjalankan program
ini? Sekarang jika Anda diminta mengoverload
operator ekualitas operator==. Apakah
yang terjadi jika Anda mencoba menjalankan program ini?
3)
Jelaskan mengapa sebuah program
C++ menggunakan statemen
Array<
Pegawai > daftarPekerja( 100 );
4)
Jelaskan
kegunaan dari notasi berikut di dalam sebuah program C++:
template< typename
T
> Array< T >::Array( int s )
No comments:
Post a Comment