Friday, December 23, 2016

Bab 6. C++ Untuk Programer



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