Friday, December 23, 2016

Bab 4. C++ Untuk Programer



Bab. 4 Pewarisan

Tujuan Instruksional
      ·         Kelas basis dan kelas terderivasi.
      ·         Anggota protected.
       ·         Relasi antara kelas basis dan kelas terderivasi.
·         Konstruktor dan destruktor di dalam kelas terderivasi.
·         Pewarisan public, private, dan protected.





4.1 Introduksi

Bab ini akan melanjutkan diskusi tentang pemrograman berorientasi objek dengan mengenalkan konsep pewarisan. Pewarisan merupakan suatu bentuk pendaur-ulangan kode dimana di dalamnya Anda dapat menciptakan suatu kelas yang menyerap kapabilitas-kapabilitas yang dimiliki oleh kelas yang sudah ada, kemudian memperbaikinya untuk tujuan Anda. Pendaur-ulangan kode dapat menghemat waktu dalam pengembangan program dengan mengambil keuntungan dari kelas yang sudah teruji dan berkualitas tinggi.

Ketika menciptakan sebuah kelas, daripada menulis anggota data dan anggota fungsi yang baru, Anda bisa menciptakan kelas baru yang mewarisi anggota-anggota dari kelas yang sudah ada. Kelas yang sudah ada ini disebut dengan kelas basis, dan kelas baru yang mewarisi tersebut dikenal dengan kelas terderivasi. Bahasa pemrograman lain seperti Java dan C# menyebutkan kelas basis sebagai superkelas dan kelas terderivasi sebagai subkelas. Kelas terderivasi merepresentasikan grup-grup objek yang lebih spesifik.

C++ menawarkan pewarisan public, protected, dan private. Pada bab ini, akan dikonsentrasikan untuk membahas pewarisan public dan hanya menjelaskan secara singkat tentang dua jenis pewarisan yang lain. Dengan pewarisan public, setiap objek dari kelas terderivasi merupakan objek dari kelas basis yang diwarisi oleh kelas terderivasi tersebut. Tetapi, sebaliknya, objek kelas basis bukan merupakan objek dari kelas terderivasinya. Sebagai contoh, jika Anda memiliki Kendaraan sebagai kelas basis dan Mobil sebagai kelas terderivasinya, maka semua Mobil adalah Kendaraan, tetapi tidak semua Kendaraan adalah Mobil, karena Kendaraan bisa juga berupa Truk, Becak, Motor, dan lainnya.

Gambar 4.1 Beberapa contoh pewarisan

Kelas Basis
Kelas Terderivasi
Mahasiswa

Bangun

Pinjaman

Karyawan

Akun
MahasiswaSarjana, MahasiswaPascaSarjana

Lingkaran, SegiTiga, PersegiPanjang, Kubus

PinjamanPeruhaman, PinjamanMobil, PijamanMultiGuna

Fakultas, Staf

AkunSimpanan, AkunPinjaman

Anda perlu membedakan antara relasi adalah-suatu dan relasi memiliki-suatu. Relasi adalah-suatu merepresentasikan pewarisan. Di dalam relasi adalah-suatu, sebuah objek dari kelas terderivasi dapat juga diperlakukan sebagai objek kelas basis. Sebagai contoh, sebuah Mobil adalah sebuah Kendaraan, jadi sembarang atribut dan watak dari Kendaraan juga merupakan atribut dan watak dari Mobil. Kebalikannya, relasi adalah-suatu merepresentasikan komposisi. Di dalam relasi adalah-suatu, sebuah objek memuat satu atau lebih objek dari kelas lain sebagai anggota. Sebagai contoh, sebuah Mobil memiliki banyak komponen, seperti Ban, Rem, dan lainnya.


4.2 Kelas Basis dan Kelas Terderivasi
Gambar 4.1 mencantumkan beberapa contoh sederhana dari kelas basis dan kelas terderivasi. Kelas basis cenderung lebih umum dan kelas terderivasi cenderung lebih spesifik. Karena setiap objek kelas terderivasi merupakan objek kelas basisnya, dan satu kelas basis dapat memiliki banyak kelas terderivasi, maka himpunan objek yang direpresentasikan oleh kelas basis umumnya lebih besar atau lebih umum dari himpunan objek yang direpresentasikan oleh sembarang kelas terderivasinya. Sebagai contoh, kelas basis Kendaraan merepresentasikan semua kendaraan, termasuk mobil, truk, pesawat, sepeda, dan lainnya. Kebalikannya, kelas terderivasi Mobil merepresentasikan subhimpunan yang lebih kecil dan lebih spesifik.

Relasi pewarisan membentuk hirarki kelas. Sebuah kelas basis memiliki relasi hirarkis dengan kelas-kelas terderivasinya. Meskipun masing-masing kelas dapat eksis secara independen, begitu kelas tersebut diterapkan di dalam relasi pewarisan, maka ia menjadi terafiliasi dengan kelas-kelas lain. Kelas basis

Hirarki Kelas AnggotaKomunitas
Sekarang akan dikembangkan hirarki pewarisan lima level (yang direpresentasikan oleh diagram kelas UML pada Gambar 4.2). Komunitas universitas memiliki ribuan AnggotaKomunitas. AnggotaKomunitas memuat Karyawan, Mahasiswa, dan Alumnus. Karyawan bisa memuat Fakultas dan Staf. Fakultas bisa memuat Pengelola dan Dosen. Beberapa Pengelola juga bisa merupakan Dosen. Digunakan pewarisan jamak untuk membentuk kelas PengelolaDosen. Dengan pewarisan tunggal, sebuah kelas diderivasi hanya dari satu kelas basis. Dengan pewarisan jamak, sebuah kelas terderivasi mewarisi satu atau lebih kelas basis.

Setiap panah di dalam hirarki (Gambar 4.2) merepresentasikan relasi adalah-suatu. Sebagai contoh, bila diikuti arah panah dalam hirarki kelas, Anda dapat menyatakan bahwa “suatu Karyawan adalah suatu AnggotaKomunitas” dan “suatu Dosen adalah suatu anggota Fakultas”. AnggotaKomunitas merupakan kelas basis langsung bagi Karyawan, Mahasiswa, dan Alumnus. Selain itu, AnggotaKomunitas adalah kelas basis tak-langsung bagi semua kelas lain dalam diagram.


Gambar 4.2 Hirarki pewarisan untuk AnggotaKomunitas



Hirarki Kelas Bangun
Sekarang perhatikan hirarki pewarisan Bangun pada Gambar 4.3. Hirarki ini dimulai dengan kelas basis Bangun. Kelas BangunDuaDimensi dan BangunTigaDimensi diderivasi dari kelas basis Bangun. Level ketiga dari hirarki ini memuat tipe yang lebih spesifik dari BangunDuaDimensi dan dari BangunTigaDimensi. Sama seperti pada Gambar 4.2, Anda dapat mengikuti panah dari bawah diagram ke arah atas sampai kelas basis teratas di dalam hirarki ini untuk mengidentifikasi beberapa relasi adalah-suatu. Misalnya, suatu SegiTiga adalah suatu BangunDuaDimensi dan adalah suatu Bangun, sedangkan suatu Tabung adalah suatu BangunTigaDimensi dan adalah suatu Bangun.


Gambar 4.3 Hirarki pewarisan Bangun


Untuk menspesifikasi bahwa kelas BangunDuaDimensi (Gambar 4.3) diderivasi dari (mewarisi dari) kelas Bangun, definisi kelas BangunDuaDimensi harus dimulai dengan:

class BangunDuaDimensi : public Bangun

Ini merupakan contoh pewarisan public, yang paling umum digunakan. Nanti pada gilirannya akan didiskusikan perihal pewarisan private dan pewarisan protected. Pada pewarisan public, anggota public kelas basis menjadi anggota public kelas terderivasi, dan anggota protected kelas basis menjadi anggota protected kelas terderivasi.


4.3 Anggota protected
Anggota public suatu kelas basis dapat diakses dari dalam tubuh kelas tersebut dan dari tempat manapun yang dapat dilakukan program (misalnya lewat nama, referensi, atau pointer) di dalam kelas basis tersebut atau dari salah satu kelas terderivasinya.Anggota private suatu kelas basis dapat diakses dari dalam tubuh kelas tersebut dan oleh friend dari kelas basis tersebut. Pada bagian ini, akan dikenalkan penspesifikasi akses protected. Penggunaan akses protected menawarkan level proteksi menengah antara akses public dan private. Anggota protected suatu kelas basis dapat diakses dari dalam tubuh kelas basis tersebut, oleh anggota dan friend dari kelas basis tersebut, dan oleh anggota dan friend dari sembarang kelas yang diderivasi dari kelas basis tersebut.

Fungsi anggota kelas terderivasi dapat merujuk ke anggota protected dan public dari kelas basisnya hanya dengan menggunakan nama anggota. Ketika sebuah fungsi anggota kelas terderivasi mendefinisikan-ulang fungsi anggota kelas basis, maka fungsi anggota kelas basis tersebut masih bisa diakses dari kelas terderivasi dengan memberikan prefiks berupa nama anggota kelas basis dengan nama kelas basis dan operator resolusi skop (::).

4.4 Relasi Antara Kelas Basis dan Kelas Terderivasi
Pada bagian ini, Anda akan menggunakan hirarki pewarisan yang memuat beberapa tipe karyawan di dalam aplikasi penggajian perusahaan untuk mendiskusikan relasi antara kelas basis dan kelas terderivasi. Karyawan komisi (yang direpresentasikan sebagai objek kelas basis) dibayar berdasarkan persentasi penjualan, sedangkan karyawan komisi bergaji pokok (yang direpresentasikan sebagai objek kelas terderivasi dibayar berdasarkan gaji pokok dan persentase penjualan. Selanjutnya diskusi ini akan dibagi menjadi karyawan komisi dan karyawan komisi bergaji pokok dalam lima contoh ke depan.

4.4.1 Menciptakan dan Menggunakan Kelas KaryawanKomisi
Sekarang akan diperiksa definisi kelas KaryawanKomisi (Gambar 4.4 – 4.5). Header KaryawanKomisi (Gambar 4.4) menspesifikasi layanan public dari kelas KaryawanKomisi, yang menyertakan sebuah konstruktor (baris 12-13) dan fungsi anggota penghasilan (baris 30) dan tampil (baris 31). Baris 15-28 mendeklarasikan beberapa fungsi get dan set (public) yang memanipulasi anggota-anggota data kelas (dideklarasikan pada baris 33-37) namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi. Fungsi anggota setPenjualanKotor (didefinisikan pada baris 56-62, Gambar 4.5) dan setBesarKomisi (didefinisikan pada baris 71-77, Gambar 4.5) dipakai untuk memvalidasi argumen-argumennya sebelum menugaskan nilai-nilai kepada anggota-anggota data penjualanKotor dan besarKomisi.

Gambar 4.4 Definisi Kelas KaryawanKomisi

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 4.4: KaryawanKomisi.h
// Definisi kelas KaryawanKomisi merepresentasikan seorang karyawan komisi.
#ifndef KOMISI_H
#define KOMISI_H

#include <string> // Kelas string standard C++
using namespace std;

class KaryawanKomisi
{
public:
  KaryawanKomisi( const string &, const string &, const string &,
  double = 0.0, double = 0.0 );

  void setNamaPertama( const string & ); // menetapkan nama pertama
  string getNamaPertama() const; // mengembalikan nama pertama

  void setNamaAkhir( const string & ); // menetapkan nama akhir
  string getNamaAkhir() const; // mengembalikan nama akhir

  void setNomorKTP( const string & ); // menetapkan nomor KTP
  string getNomorKTP() const; // mengembalikan nomor KTP

  void setPenjualanKotor( double ); // menetapkan jumlah penjualan kotor
  double getPenjualanKotor() const; // mengembalikan jumlah penjualan kotor

  void setBesarKomisi( double ); // menetapkan besar komisi (persentase)
  double getBesarKomisi() const; // mengembalikan besar komisi

  double penghasilan() const; // menghitung penghasilan
  void tampil() const; // menampilkan objek KaryawanKomisi
private:
  string namaPertama;
  string namaAkhir;
  string nomorKTP;
  double penjualanKotor; // penjualan kotor mingguan
  double besarKomisi; // persentasi komisi
}; // akhir dari kelas KaryawanKomisi

#endif

Gambar 4.5 Definisi Fungsi Anggota Kelas KaryawanKomisi

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Gambar 4.5: KaryawanKomisi.cpp
// Definisi fungsi anggota kelas KaryawanKomisi.
#include <iostream>
#include "KaryawanKomisi.h" // definisi kelas KaryawanKomisi
using namespace std;

// konstruktor
KaryawanKomisi::KaryawanKomisi(
    const string &pertama, const string &akhir, const string &ktp,
    double penjualan, double komisi )
{
  namaPertama = pertama; // seharusnya divalidasi
  namaAkhir = akhir; // seharusnya divalidasi
  nomorKTP = ktp; // seharusnya divalidasi
  setPenjualanKotor( penjualan ); // memvalidasi dan menyimpan penjualan kotor
  setBesarKomisi( komisi ); // memvalidasi dan menyimpan besar komisi
} // akhir dari konstruktor KaryawanKomisi

// menetapkan nama pertama
void KaryawanKomisi::setNamaPertama( const string &pertama )
{
  namaPertama = pertama; // seharusnya divalidasi
} // akhir dari fungsi setNamaPertama

// mengembalikan nama pertama
string KaryawanKomisi::getNamaPertama() const
{
  return namaPertama;
} // akhir dari fungsi getNamaPertama

// menetapkan nama akhir
void KaryawanKomisi::setNamaAkhir( const string &akhir )
{
  namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir

// mengembalikan nama akhir
string KaryawanKomisi::getNamaAkhir() const
{
  return namaAkhir;
} // akhir dari fungsi getNamaAkhir

// menetapkan nomor kartu penduduk
void KaryawanKomisi::setNomorKTP( const string &ktp )
{
  nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP

// mengembalikan nomor kartu penduduk
string KaryawanKomisi::getNomorKTP() const
{
  return nomorKTP;
} // akhir dari fungsi getNomorKTP

// menetapkan jumlah penjualan kotor
void KaryawanKomisi::setPenjualanKotor( double penjualan )
{
  if ( penjualan >= 0.0 )
    penjualanKotor = penjualan;
  else
    throw invalid_argument( "penjualan kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor

// menghasilkan jumlah penjualan kotor
double KaryawanKomisi::getPenjualanKotor() const
{
  return penjualanKotor;
} // akhir dari fungsi penjualanKotor

// menetapkan besar komisi
void KaryawanKomisi::setBesarKomisi( double komisi )
{
  if ( komisi > 0.0 && komisi < 1.0 )
    besarKomisi = komisi;
  else
    throw invalid_argument( "besar komisi harus di antara > 0.0 dan < 1.0" );
 } // akhir dari fungsi setBesarKomisi

// mengembalikan besar komisi
double KaryawanKomisi::getBesarKomisi() const
{
  return besarKomisi;
} // akhir dari fungsi getBesarKomisi

// menghitung penghasilan
double KaryawanKomisi::penghasilan() const
{
  return besarKomisi * penjualanKotor;
} // akhir dari fungsi penghasilan

// menampilkan objek KaryawanKomisi
void KaryawanKomisi::tampil() const
{
  cout << "karyawan komisi: " << namaPertama << ' ' << namaAkhir
    << "\nnomor kartu penduduk: " << nomorKTP
    << "\npenjualan kotor: " << penjualanKotor
    << "\nbesar komisi: " << besarKomisi;
} // akhir dari fungsi tampil

Konstruktor KaryawanKomisi
Definisi konstruktor KaryawanKomisi tidak menggunakan sintaks penginisialisasi anggota di dalam beberapa contoh ke depan, sehingga Anda dapat mendemonstrasikan bagaimana penspesifikasi private dan protected mempengaruhi akses anggota di dalam kelas terderivasi. Seperti yang ditunjukkan pada Gambar 4.5, baris 12-14, nilai-nilai ditugaskan kepada anggota-anggota data namaPertama, namaAkhir, dan nomorKTP di dalam tubuh konstruktor. Selanjutnya pada bagian ini, kembali akan digunakan daftar penginisialisasi anggota di dalam konstruktor.

Fungsi Anggota penghasilan dan tampil pada Kelas KaryawanKomisi
Fungsi anggota penghasilan (baris 86-89) menghitung penghasilkan KaryawanKomisi. Baris 88 mengalikan besarKomisi dengan penjualanKotor dan memberikan nilai balik hasil perkalian tersebut. Fungsi anggota tampil (baris 92-98) menampilkan nilai-nilai anggota daya objek KaryawanKomisi.

Menguji Kelas KaryawanKomisi
Gambar 4.6 menguji kelas KaryawanKomisi. Baris 11-12 menginstansiasi objek karyawan dari kelas KaryawanKomisi dan memanggil konstruktor KaryawanKomisi untuk menginisialisasi objek tersebut dengan “Adam” sebagai nama pertama, “Napitupulu” sebagai nama akhir, “222-22-2222” sebagai nomor KTP, 10000 sebagai jumlah penjualan kotor, dan .06 sebagai besar komisi. Baris 19-24 menggunakan beberapa fungsi get (dari objek karyawan) untuk menampilkan nilai-nilai anggota data. Baris 26-27 memanggil fungsi anggota setPenjualanKotor dan setBesarKomisi untuk mengubah nilai-nilai anggota data penjualanKotor dan besarKomisi. Baris 31 kemudian memanggil fungsi anggota tampil untuk menampilkan informasi KaryawanKomisi yang telah diperbarui. Terakhir, baris 34 menampilkan penghasilan KaryawanKomisi, dihitung menggunakan fungsi anggota penghasilan dengan nilai-nilai anggota data penjualanKotor dan besarKomisi yang telah diperbarui.

Gambar 4.6 Menguji Kelas KaryawanKomisi

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
// Gambar 4.6: gambar4_06.cpp
// Menguji kelas KaryawanKomisi.
#include <iostream>
#include <iomanip>
#include "KaryawanKomisi.h" // definisi kelas KaryawanKomisi
using namespace std;

int main()
{
  // menginstansiasi suatu objek KaryawanKomisi
  KaryawanKomisi karyawan(
    "Adam", "Napitupulu", "222-22-2222", 10000, .06 );

  // menetapkan fotmat keluaran pecahan
  cout << fixed << setprecision( 2 );

  // mendapatkan data karyawan komisi
  cout << "Informasi karyawan didepatkan dengan fungsi get: \n"
    << "\nNama pertama adalah " << karyawan.getNamaPertama()
    << "\nNama akhir adalah " << karyawan.getNamaAkhir()
    << "\nNomor kartu penduduk adalah "
    << karyawan.getNomorKTP()
    << "\nPenjualan kotor adalah " << karyawan.getPenjualanKotor()
    << "\nBesar komisi adalah " << karyawan.getBesarKomisi() << endl;

  karyawan.setPenjualanKotor( 8000 ); // menetapkan penjualan kotor
  karyawan.setBesarKomisi( .1 ); // mentepakan besar komisi

  cout << "\nInformasi karyawan terperbarui ditampilkan dengan fungsi tampil: \n"
    << endl;
  karyawan.tampil(); // menampilkan informasi karyawan yang baru

  // menampilkan penghasilan karyawan
  cout << "\n\nPenghasilan karyawan: Rp. " << karyawan.penghasilan() << endl;
 } // akhir dari main

Informasi karyawan didepatkan dengan fungsi get:

Nama pertama adalah Adam
Nama akhir adalah Napitupulu
Nomor kartu penduduk adalah 222-22-2222
Penjualan kotor adalah 10000.00
Besar komisi adalah 0.06

Informasi karyawan terperbarui ditampilkan dengan fungsi tampil:

karyawan komisi: Adam Napitupulu
nomor kartu penduduk: 222-22-2222
penjualan kotor: 8000.00
besar komisi: 0.10

Penghasilan karyawan: Rp. 800.00


4.4.2 Menciptakan Kelas KaryawanKomisiPlusPokok Tanpa Pewarisan
Sekarang akan didiskusikan bagian menciptakan dan menguji (kelas yang baru dan independen) kelas KaryawanKomisiPlusPokok (Gambar 4.7 – 4.8), yang memuat nama pertama, nama akhir, nomor KTP, jumlah penjualan kotor, besar komisi, dan gaji pokok.

Gambar 4.7 Definisi Kelas KaryawanKomisiPlusPokok

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
// Gambar 4.7: KaryawanKomisiPlusPokok.h
// Definisi kelas KaryawanKomisiPlusPokok merepresentasikan seorang karyawan komisi
// yang menerima gaji pokok selain komisi.
#ifndef POKOK_PLUS_H
#define POKOK_PLUS_H

#include <string> // Kelas string standard C++
using namespace std;

class KaryawanKomisiPlusPokok
{
public:
   KaryawanKomisiPlusPokok( const string &, const string &, const string &,
   double = 0.0, double = 0.0, double = 0.0 );

   void setNamaPertama( const string & ); // menetapkan nama pertama
   string getNamaPertama() const; // mengembalikan nama pertama

   void setNamaAkhir( const string & ); // menetapkan nama akhir
   string getNamaAkhir() const; // mengembalikan nama akhir

   void setNomorKTP( const string & ); // menetapkan nomor KTP
   string getNomorKTP() const; // mengembalikan nomor KTP

   void setPenjualanKotor( double ); // menetapkan jumlah penjualan kotor
   double getPenjualanKotor() const; // mengembalikan jumlah penjualan kotor

   void setBesarKomisi( double ); // menetapkan besar komisi (persentase)
   double getBesarKomisi() const; // mengembalikan besar komisi

   void setGajiPokok( double ); // menetapkan gaji pokok
   double getGajiPokok() const; // mengembalikan gaji pokok

   double penghasilan() const; // menghitung penghasilan
   void tampil() const; // menampilkan objek KaryawanKomisiPlusPokok
private:
   string namaPertama;
   string namaAkhir;
   string nomorKTP;
   double penjualanKotor; // penjualan kotor mingguan
   double besarKomisi; // persentasi komisi
   double gajiPokok; // gaji pokok
}; // akhir dari kelas KaryawanKomisiPlusPokok

#endif

Gambar 4.8 Definisi Fungsi Anggota Kelas KaryawanKomisiPlusPokok

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Gambar 4.8: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;

// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
    const string &pertama, const string &akhir, const string &ktp,
    double penjualan, double komisi, double gaji )
{
  namaPertama = pertama; // seharusnya divalidasi
  namaAkhir = akhir; // seharusnya divalidasi
  nomorKTP = ktp; // seharusnya divalidasi
  setPenjualanKotor( penjualan ); // memvalidasi dan menyimpan penjualan kotor
  setBesarKomisi( komisi ); // memvalidasi dan menyimpan besar komisi
  setGajiPokok( gaji ); // memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor KaryawanKomisiPlusPokok

// menetapkan nama pertama
void KaryawanKomisiPlusPokok::setNamaPertama( const string &pertama )
{
  namaPertama = pertama; // seharusnya divalidasi
} // akhir dari fungsi setNamaPertama

// mengembalikan nama pertama
string KaryawanKomisiPlusPokok::getNamaPertama() const
{
  return namaPertama;
} // akhir dari fungsi getNamaPertama

// menetapkan nama akhir
void KaryawanKomisiPlusPokok::setNamaAkhir( const string &akhir )
{
  namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir

// mengembalikan nama akhir
string KaryawanKomisiPlusPokok::getNamaAkhir() const
{
  return namaAkhir;
} // akhir dari fungsi getNamaAkhir

// menetapkan nomor kartu penduduk
void KaryawanKomisiPlusPokok::setNomorKTP(
    const string &ktp )
{
  nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP

// mengembalikan nomor kartu penduduk
string KaryawanKomisiPlusPokok::getNomorKTP() const
{
  return nomorKTP;
} // akhir dari fungsi getNomorKTP

// menetapkan jumlah penjualan kotor
void KaryawanKomisiPlusPokok::setPenjualanKotor( double penjualan )
{
  if ( penjualan >= 0.0 )
    penjualanKotor = penjualan;
  else
    throw invalid_argument( "penjualan kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor

// menghasilkan jumlah penjualan kotor
double KaryawanKomisiPlusPokok::getPenjualanKotor() const
{
  return penjualanKotor;
} // akhir dari fungsi penjualanKotor

// menetapkan besar komisi
void KaryawanKomisiPlusPokok::setBesarKomisi( double komisi )
{
  if ( komisi > 0.0 && komisi < 1.0 )
    besarKomisi = komisi;
  else
    throw invalid_argument( "besar komisi harus di antara > 0.0 dan < 1.0" );
 } // akhir dari fungsi setBesarKomisi

// mengembalikan besar komisi
double KaryawanKomisiPlusPokok::getBesarKomisi() const
{
  return besarKomisi;
} // akhir dari fungsi getBesarKomisi

// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double gaji )
{
  if ( gaji >= 0.0 )
    gajiPokok = gaji;
  else
    throw invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok

// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
  return gajiPokok;
} // akhir dari fungsi getGajiPokok

// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
  return gajiPokok + ( besarKomisi * penjualanKotor );
} // akhir dari fungsi penghasilan

// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
   cout << "karyawan komisi bergaji pokok: " << namaPertama << ' '
     << namaAkhir << "\nnomor kartu penduduk: " << nomorKTP
     << "\npenjualan kotor: " << penjualanKotor
     << "\nbesar komisi: " << besarKomisi
     << "\ngaji pokok: " << gajiPokok;
} // akhir dari fungsi tampil

Mendefinisikan Kelas KaryawanKomisiPlusPokok
Header KaryawanKomisiPlusPokok (Gambar 4.7) menspesifikasi layanan public dari kelas KaryawanKomisiPlusPokok, yang menyertakan konstruktor KaryawanKomisiPlusPokok (baris 13-14) dan fungsi anggota penghasilan (baris 34) dan tampil (baris 35). Baris 16-32 mendeklarasikan beberapa fungsi get dan set untuk anggota-anggota data private (dideklarasikan pada baris 37-42) namaPertama, namaAkhir, nomorKTP, penjualanKotor, besarKomisi, dan gajiPokok. Semua variabel dan fungsi anggota merupakan fitur penting untuk karyawan komisi bergaji pokok. Perhatikan kesamaan kode ini dengan kode kelas KaryawanKomisi (Gambar 4.4 – 4.5).

Fungsi anggota penghasilan dari kelas KaryawanKomisiPlusPokok (didefinisikan pada baris 100-103 pada Gambar 4.8) menghitung penghasilan karyawan komisi bergaji pokok. Baris 102 memberikan nilai balik berupa hasil penjumlahan dari gaji pokok dengan gaji karyawan komisi.

Menguji Kelas KaryawanKomisiPlusPokok
Gambar 4.9 menguji kelas KaryawanKomisiPlusPokok. Baris 11-12 menginstansiasi objek karyawan dari kelas KaryawanKomisiPlusPokok, dengan melewatkan “Rotua”, “Marolop”, “333-33-3333”, 5000, .04, dan 300 kepada konstruktor sebagai nama pertama, nama akhir, nomor kartu penduduk, penjualan kotor, besar komisi, dan gaji pokok. Baris 19-25 menggunakan beberapa fungsi get untuk mengambil nilai-nilai anggota data objek untuk ditampilkan. Baris 27 memanggil fungsi anggota setGajiPokok untuk mengubah besaran gaji pokok. Fungsi anggota setGajiPokok (Gambar 4.8, baris 88-94) memastikan bahwa anggota data gajiPokok tidak ditugasi nilai negatif, karena gaji pokok karyawan tidak bisa bernilai negatif. Baris 31 pada Gambar 4.9 memanggil fungsi anggota tampil untuk menampilkan informasi KaryawanKomisiPlusPokok yang telah diperbarui, dan baris 34 memanggil fungsi anggota penghasilkan untuk menampilkan penghasilan KaryawanKomisiPlusPokok.

Gambar 4.9 Definisi Kelas KaryawanKomisiPlusPokok

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
// Gambar 4.9: gambar4_09.cpp
// Menguji kelas KaryawanKomisiPlusPokok.
#include <iostream>
#include <iomanip>
#include "KaryawanKomisiPlusPokok.h"
using namespace std;

int main()
{
  // menginstansiasi objek KaryawanKomisiPlusPokok
  KaryawanKomisiPlusPokok
     karyawan( "Rotua", "Marolop", "333-33-3333", 5000, .04, 300 );

  // menetapkan format keluaran pecahan
  cout << fixed << setprecision( 2 );

  // mendapatkan data karyawan komisi
  cout << "Informasi karyawan didapatkan dengan fungsi-fungsi get: \n"
    << "\nNama pertama adalah " << karyawan.getNamaPertama()
    << "\nNama akhir adalah " << karyawan.getNamaAkhir()
    << "\nNomor kartu penduduk adalah "
    << karyawan.getNomorKTP()
    << "\nPenjualan kotor adalah " << karyawan.getPenjualanKotor()
    << "\nBesar komisi adalah " << karyawan.getBesarKomisi()
    << "\nGaji pokok adalah " << karyawan.getGajiPokok() << endl;

  karyawan.setGajiPokok( 1000 ); // menetapkan gaji pokok

  cout << "\nInformasi karyawan terperbarui ditampilkan oleh fungsi tampil: \n"
    << endl;
  karyawan.tampil(); // menampilkan informasi karyawan yang baru

  // menampilkan penghasilan karyawan
  cout << "\n\nPenghasilan karyawan: Rp. " << karyawan.penghasilan() << endl;
} // akhir dari main

Informasi karyawan didapatkan dengan fungsi-fungsi get:

Nama pertama adalah Rotua
Nama akhir adalah Marolop
Nomor kartu penduduk adalah 333-33-3333
Penjualan kotor adalah 5000.00
Besar komisi adalah 0.04
Gaji pokok adalah 300.00

Informasi karyawan terperbarui ditampilkan oleh fungsi tampil:

karyawan komisi bergaji pokok: Rotua Marolop
nomor kartu penduduk: 333-33-3333
penjualan kotor: 5000.00
besar komisi: 0.04
gaji pokok: 1000.00

Penghasilan karyawan: Rp. 1200.00

Mengeksploarasi Kesamaan Kelas KaryawanKomisiPlusPokok dan Kelas KaryawanKomisi
Hampir semua kode untuk kelas KaryawanKomisiPlusPokok (Gambar 4.7 - 4.8) sama, bahkan hampir identik, dengan kode untuk kelas KaryawanKomisi (Gambar 4.4 – 4.5). Sebagai contoh, dalam kelas KaryawanKomisiPlusPokok, anggota-anggota data private namaPertama dan namaAkhir dan fungsi-fungsi anggota setNamaPertama, getNamaPertama, setNamaAkhir, dan getNamaAkhir identik dengan yang ada pada kelas KaryawanKomisi. Kelas KaryawanKomisiPlusPokok dan KaryawanKomisi juga sama-sama memuat anggota-anggota data private nomorKTP, besarBonus, dan penjualanKotor, berikut dengan beberapa fungsi get dan set untuk memanipulasi anggota-anggota tersebut. Selain itu, konstruktor KaryawanKomisiPlusPokok identik dengan konstruktor kelas KaryawanKomisi, kecuali bahwa konstruktor KaryawanKomisiPlusPokok juga menetapkan gajiPokok. Tambahan lain pada kelas KaryawanKomisiPlusPokok adalah anggota data private, gajiPokok, dan fungsi anggota setGajiPokok dan getGajiPokok. Fungsi anggota tampil pada kelas KaryawanKomisiPlusPokok hampir identik dengan yang ada pada kelas KaryawanKomisi, kecuali bahwa tampil pada kelas KaryawanKomisiPlusPokok menampilkan juga anggota data gajiPokok.

Secara literal, Anda bisa menyalin kelas KaryawanKomisi ke dalam KaryawanKomisiPlusPokok, kemudian memodifikasinya untuk menyertakan gaji pokok dan beberapa fungsi anggota untuk memanipulasi gaji pokok. Pendekatan salin-dan-tempel ini sangat rentan terhadap kesalahan dan cukup memakan waktu.

4.4.3 Menciptakan Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok
Sekarang akan diciptakan dan diuji suatu kelas KaryawanKomisiPlusPokok yang baru (Gambar 4.10 – 4.11) yang mewarisi dari kelas KaryawanKomisi (Gambar 4.4 – 4.5). Pada contoh ini, suatu objek KaryawanKomisiPlusPokok adalah sebuah objak KaryawanKomisi (karena pewarisan mewariskan kapabilitas dari kelas KaryawanKomisi), tetapi kelas KaryawanKomisiPlusPokok juga memiliki anggota data gajiPokok (Gambar 4.10, baris 23). Titik-dua (:) pada baris 11 di dalam definisi kelas mengindikasikan pewarisan. Katakunci public mengindikasikan tipe pewarisan. Sebagai kelas terderivasi (dibentuk dengan pewarisan public), KaryawanKomisiPlusPokok mewarisi semua anggota kelas KaryawanKomisi, kecuali konstruktor, karena setiap kelas menyediakan konstruktornya sendiri yang spesifik dengan kelas tersebut (destruktor juga tidak diwarisi). Jadi, layanana public dari kelas KaryawanKomisiPlusPokok mencakup konstruktornya (baris 14-15) dan beberapa fungsi anggota public yang diwarisi dari kelas KaryawanKomisi. Meskipun Anda tidak bisa melihat semua fungsi yang diwarisi di dalam kode sumber KaryawanKomisiPlusPokok, tetapi semua fungsi tersebut adalah bagian dari kelas terderivasi KaryawanKomisiPlusPokok. Layanan public dari kelas terderivasi juga mencakup beberapa fungsi anggota setGajiPokok, getGajiPokok, penghasilan, dan tampil (baris 17-21).

Gambar 4.10 Definisi Kelas KaryawanKomisiPlusPokok Mengindikasikan Relasi Pewarisan dengan Kelas KaryawanKomisi

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
// Gambar 4.10: KaryawanKomisiPlusPokok.h
// Kelas KaryawanKomisiPlusPokok diderivasi dari kelas
// KaryawanKomisi.
#ifndef POKOK_PLUS_H
#define POKOK_PLUS_H

#include <string> // Kelas string standard C++
#include "KaryawanKomisi.h"
using namespace std;

class KaryawanKomisiPlusPokok : public KaryawanKomisi
{
public:
  KaryawanKomisiPlusPokok( const string &, const string &,
    const string &, double = 0.0, double = 0.0, double = 0.0 );

  void setGajiPokok( double ); // menetapkan gaji pokok
  double getGajiPokok() const; // mengembalikan gaji pokok

  double penghasilan() const; // menghitung penghasilan
  void tampil() const; // menampilkan objek KaryawanKomisiPlusPokok
private:
  double gajiPokok; // gaji pokok
}; // akhir dari kelas KaryawanKomisiPlusPokok

#endif

Gambar 4.11 File Implementasi KaryawanKomisiPlusPokok: Data private Kelas Basis Tidak Bisa Diakses dari Kelas Terderivasi

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 4.11: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;

// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
    const string &pertama, const string &akhir, const string &ktp,
    double penjualan, double komisi, double gaji )
    // secara eksplisit memanggil konstruktor kelas basis
    : KaryawanKomisi( pertama, akhir, ktp, penjualan, komisi )
{
  setGajiPokok( gaji ); // memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor KaryawanKomisiPlusPokok

// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double gaji )
{
  if ( gaji >= 0.0 )
    gajiPokok = gaji;
  else
    throw invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok

// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
  return gajiPokok;
} // akhir dari fungsi getGajiPokok

// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
  // kelas terderivasi tidak bisa mengakses data private pada kelas basis
  return gajiPokok + ( besarKomisi * penjualanKotor );
} // akhir dari fungsi penghasilan

// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
    // kelas terderivasi tidak bisa mengakses data private pada kelas basis
       cout << "karyawan komisi bergaji pokok: " << namaPertama << ' '
       << namaAkhir << "\nnomor kartu penduduk: " << nomorKTP
    << "\npenjualan kotor: " << penjualanKotor
    << "\nbesar komisi: " << besarKomisi
    << "\ngaji pokok: " << gajiPokok;
} // akhir dari fungsi tampil

c:\c++\karyawankomisipluspokok.cpp(36) : error C2248: 'besarKomisi' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(37) : see declaration of 'besarKomisi'

c:\c++\karyawankomisipluspokok.cpp(36) : error C2248: 'penjualanKotor' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(36) : see declaration of 'penjualanKotor'

c:\c++\karyawankomisipluspokok.cpp(43) : error C2248: 'namaPertama' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(33) : see declaration of 'namaPertama'

c:\c++\karyawankomisipluspokok.cpp(44) : error C2248: 'namaAkhir' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(34) : see declaration of 'namaAkhir'

c:\c++\karyawankomisipluspokok.cpp(45) : error C2248: 'nomorKTP' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(35) : see declaration of 'nomorKTP'

c:\c++\karyawankomisipluspokok.cpp(46) : error C2248: 'penjualanKotor' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(36) : see declaration of 'penjualanKotor'

c:\c++\karyawankomisipluspokok.cpp(47) : error C2248: 'besarKomisi' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(37) : see declaration of 'besarKomisi'

Gambar 4.11 menunjukkan implementasi fungsi anggota kelas KaryawanKomisiPlusPokok. Konstruktor (baris 8-15) mengintroduksi sintaks penginisialisasi kelas basis (baris 12), yang menggunakan sebuah penginisialisasi anggota untuk melewatkan argumen kepada konstruktor kelas basis (KaryawanKomisi). C++ mensyaratkan bahwa konstruktor kelas terderivasi memanggil konstruktor kelas basis untuk menginisialisasi anggota-anggota data kelas basis yang diwariskan kepada kelas terderivasi. Baris 12 melakukan hal ini secara eksplisit dengan memanggil konstruktor KaryawanKomisi lewat nama, melewatkan parameter-parameter konstruktor pertama, akhir, ktp, penjualan, dan komisi sebagai argumen untuk menginisialisasi anggota-anggota data kelas basis namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi. Jika konstruktor KaryawanKomisiPlusPokok tidak memanggil konstruktor KaryawanKomisi secara eksplisit, maka C++ akan mencoba memanggil konstruktor default KaryawanKomisi secara implisit. Karena kelas KaryawanKomisi tidak memiliki konstruktor default, maka kompiler akan mengeluarkan pesan error. Ingat bahwa kompiler menyediakan konstruktor default tanpa parameter bagi sembarang kelas yang tidak secara eksplisit menyertakan sebuah konstruktor. Tetapi, KaryawanKomisi secara eksplisit menyertakan sebuah konstruktor, sehingga konstruktor default tidak disediakan.

Error Kompilasi dari Pengaksesan Anggota Data private Kelas Basis
Kompiler membangkitkan error pada untuk baris 36 pada baris 7.11 karena anggota data private, besarKomisi dan penjualanKotor, pada kelas KaryawanKomisi, tidak diijinkan diakses oleh fungsi anggota kelas terderivasi KaryawanKomisiPlusPokok. Kompiler mengeluarkan error lain pada baris 43-46  karena alasan yang sama. Seperti yang Anda lihat, C++ secara tegas membatasi pengaksesan anggota data private, sehingga bahkan kelas terderivasi (yang secara intim berelasi dengan kelas basisnya) tidak dapat mengakses data private kelas basis.

Mencegah Error di dalam Kelas KaryawanKomisiPlusPokok
Pada Gambar 4.11 disengaja untuk mencantumkan kode error untuk menekankan bahwa fungsi anggota kelas terderivasi tidak dapat mengakses data private kelas basisnya. Error di dalam KaryawanKomisiPlusPokok dapat dicegah dengan menggunakan fungsi anggota get yang diwarisi dari KaryawanKomisi. Sebagai contoh, baris 36 seharusnya dapat memanggil getBesarKomisi dan getPenjualanKotor untuk mengakses anggota-anggota data private kelas KaryawanKomisi seperti besarKomisi dan penjualanKotor. Hal yang sama, baris 43-46 seharusnya dapat menggunakan fungsi anggota get yang sesuai untuk mengambil nilai-nilai anggota data kelas basis. Pada contoh berikutnya, akan ditunjukkan bagaimana menggunakan data protected yang mengijinkan Anda untuk menghindari masalah yang terjadi pada contoh ini.

Menyertakan Header Kelas Basis di dalam Header Kelas Terderivasi dengan #include
Perhatikan bahwa header kelas basis dicantumkan di dalam header kelas terderivasi (baris 8 pada Gambar 4.10). Hal ini penting karena tiga alasan. Pertama, agar kelas terderivasi bisa menggunakan nama kelas basis pada baris 11, Anda harus memberitahukan kompiler bahwa kelas basis eksis (definisi di dalam KaryawnKomisi.h yang melakukannya). Alasan kedua adalah bahwa kompiler menggunakan definisi kelas untuk menentukan ukuran sebuah objek dari kelas tersebut. Program klien yang menciptakan objek suatu kelas harus menyertakan definisi kelas (menggunakan #include) untuk memampukan kompiler untuk menyediakan sejumlah memori tertentu untuk objek tersebut. Ketika menggunakan pewarisan, ukuran objek kelas terderivasi bergantung dari anggota data yang dideklarasikan secara eksplisit di dalam definisi kelasnya dan anggota data yang diwarisi secara langsung maupun tak-langsung dari kelas basisnya.

Penyertaan definisi kelas basis pada baris 8 memampukan kompiler untuk menentukan memori yang dibutuhkan untuk anggota data kelas basis yang menjadi bagian dari suatu objek kelas terderivasi dan oleh karena itu berkontribusi menambah ukuran total objek kelas terderivasi. Alasan terakhir untuk baris 8 adalah untuk mengijinkan kompiler dalam menentukan apakah kelas terderivasi menggunakan anggota yang diwarisi dari kelas basis secara benar. Sebagai contoh, dalam program Gambar 4.10 – 4.11, kompiler menggunakan header kelas basis untuk menentukan bahwa anggota data yang sedang diakses oleh kelas terderivasi merupakan anggota data private di dalam kelas basis. Karena anggota data private tidak bisa diakses oleh kelas terderivasi, kompiler kemudian membangkitkan error. Kompiler juga menggunakan prototipe fungsi kelas basis untuk memvalidasi pemanggilan fungsi yang dilakukan oleh kelas terderivasi terhadap fungsi yang diwarisi dari kelas basis.

4.4.4 Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok Menggunakan Data protected
Agar kelas KaryawanKomisiPlusPokok dapat secara langsung mengakses anggota data kelas KaryawanKomisi (namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi), Anda perlu mendeklarasikan semua anggota tersebut sebagai protected di dalam kelas basis. Seperti yang telah dijelaskan sebelumnya, anggota protected suatu kelas basis dapat diakses oleh fungsi anggota dan fungsi friend kelas basis dan oleh fungsi anggota dan fungsi friend dari sembarang kelas yang diderivasi dari kelas basis tersebut.

Mendefinisikan Kelas KaryawanKomisi dengan Data protected
Kelas KaryawanKomisi (Gambar 4.12) sekarang mendeklarasikan anggota-anggota data namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi sebagai protected (baris 32-37) sebagai pengganti private. Implementasi fungsi anggota identik dengan yang ada pada Gambar 4.5, jadi KaryawanKomisi.cpp tidak ditampilkan di sini.

Gambar 4.12 Definisi Kelas KaryawanKomisi dengan Data protected

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 4.12: KaryawanKomisi.h
// Definisi kelas KaryawanKomisi dengan data protected.
#ifndef KOMISI_H
#define KOMISI_H

#include <string> // Kelas string standard C++
using namespace std;

class KaryawanKomisi
{
public:
  KaryawanKomisi( const string &, const string &, const string &,
  double = 0.0, double = 0.0 );

  void setNamaPertama( const string & ); // menetapkan nama pertama
  string getNamaPertama() const; // mengembalikan nama pertama

  void setNamaAkhir( const string & ); // menetapkan nama akhir
  string getNamaAkhir() const; // mengembalikan nama akhir

  void setNomorKTP( const string & ); // menetapkan nomor KTP
  string getNomorKTP() const; // mengembalikan nomor KTP

  void setPenjualanKotor( double ); // menetapkan jumlah penjualan kotor
  double getPenjualanKotor() const; // mengembalikan jumlah penjualan kotor

  void setBesarKomisi( double ); // menetapkan besar komisi (persentase)
  double getBesarKomisi() const; // mengembalikan besar komisi

  double penghasilan() const; // menghitung penghasilan
  void tampil() const; // menampilkan objek KaryawanKomisi
protected:
  string namaPertama;
  string namaAkhir;
  string nomorKTP;
  double penjualanKotor; // penjualan kotor mingguan
  double besarKomisi; // persentasi komisi
}; // akhir dari kelas KaryawanKomisi

#endif

Kelas KaryawanKomisiPlus
Definisi kelas KaryawanKomisiPlusPokok dari Gambar 4.10 – 4.11 tetap tidak berubah, jadi tidak akan ditampilkan kembali di sini. Karena KaryawanKomisiPlusPokok mewarisi kelas KaryawanKomisi terperbarui pada Gambar 4.12, objek-objek KaryawanKomisiPlusPokok dapat mengakses anggota data terwarisi yang dideklarasikan protected di dalam kelas KaryawanKomisi (yaitu namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi). Hasilnya, kompiler tidak membangkitkan error ketika mengompilasi fungsi anggota penghasilan dan tampil pada kelas KaryawanKomisiPlusPokok pada Gambar 4.11 (baris 33-37 dan 40-48). Ini menunjukkan  hak spesial yang dimiliki kelas terderivasi dalam mengakses anggota data protected milik kelas basis. Objek suatu kelas terderivasi juga dapat mengakses anggota protected di dalam sembarang kelas basis tak-langsung yang mewari kelas terderivasi tersebut.

Kelas KaryawanKomisiPlusPokok tidak mewarisi konstruktor KaryawanKomisi. Namun, konstruktor kelas KaryawanKomisiPlusPokok (Gambar 4.11, baris 8-15) memanggil konstruktor kelas KaryawanKomisi secara eksplisit menggunakan sintaks penginisialisasi anggota (baris 12). Ingat bahwa konstruktor KaryawanKomisiPlusPokok harus secara eksplisit memanggil konstruktor kelas KaryawanKomisi, karena kelas KaryawanKomisi tidak memuat konstruktor default yang dapat dipanggil secara implisit.

Menguji Kelas Kelas KaryawanKomisiPlus Termodifikasi
Untuk menguji hirarki kelas terperbarui, program pada Gambar 4.9 akan digunakan kembali. Seperti tertampil pada Gambar 4.13, keluarannya identik dengan yang ada pada Gambar 7.9. Anda telah menciptakan KaryawanKomisiPlusPokok tanpa menggunakan pewarisan dan juga menciptakan KaryawanKomisiPlusPokok menggunakan pewarisan; tetapi, kedua versi kelas tersebut memiliki fungsionalitas yang sama. Kode untuk kelas KaryawanKomisiPlusPokok (header dan file implementasi), sebanyak 74 baris, jauh lebih pendek dari pada kode untuk versi non-pewarisan, sebanyak 161 baris, karena versi pewarisan menyerap fungsionalitasnya dari KaryawanKomisi, sedangkan versi non-pewarisan tidak menyerap fungsionalitasnya dari manapun. Di samping itu, sekarang hanya terdapat satu salinan dari fungsionalitas KaryawanKomisi yang dideklarasikan dan didefinisikan di dalam kelas KaryawanKomisi. Hal ini membuat kode sumber menjadi lebih mudah dirawat, dimodifikasi dan dikembangkan.

Gambar 4.13 Data protected Kelas Basis dapat Diakses dari Kelas Terderivasi

Informasi karyawan didapatkan dengan fungsi-fungsi get:

Nama pertama adalah Rotua
Nama akhir adalah Marolop
Nomor kartu penduduk adalah 333-33-3333
Penjualan kotor adalah 5000.00
Besar komisi adalah 0.04
Gaji pokok adalah 300.00

Informasi karyawan terperbarui ditampilkan oleh fungsi tampil:

karyawan komisi bergaji pokok: Rotua Marolop
nomor kartu penduduk: 333-33-3333
penjualan kotor: 5000.00
besar komisi: 0.04
gaji pokok: 1000.00

Penghasilan karyawan: Rp. 1200.00

4.4.5 Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok Menggunakan Data private
Sekarang akan diuji kembali hirarki kelas yang ada sekali lagi, kali ini menggunakan praktek pemrograman yang benar. Kelas KaryawanKomisi sekarang mendeklarasikan anggota data namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi sebagai private seperti yang sebelumnya ditampilkan pada baris 32-37 pada Gambar 4.4.


Perubahan pada Definisi Fungsi Kelas KaryawanKomisi
Di dalam implementasi konstruktor KaryawanKomisi (Gambar 4.14, baris 8-15), Anda menggunakan penginisialisasi anggota (baris 11) untuk menetapkan nilai anggota data namaPertama, namaAkhir, dan nomorKTP. Sekarang akan ditunjukkan bagaimana kelas terderivasi KaryawanKomisiPlusPokok (Gambar 4.15) agar dapat memanggil fungsi-fungsi anggota non-private kelas basis (setNamaPertama, getNamaPertama, setNamaAkhir, getNamaAkhir, setNomorKTP, dan getNomorKTP) untuk memanipulasi anggota-anggota data tersebut.

Di dalam tubuh konstruktor dan di dalam tubuh fungsi anggota penghasilan (baris 84-87) dan fungsi anggota tampil (baris 90-97), Anda memanggil beberapa fungsi set dan get untuk mengakses anggota data private. Jika Anda memutuskan untuk mengubah nama anggota data, definisi penghasilan dan tampil tidak perlu dimodifikasi, hanya definisi beberapa metode get dan set, yang secara langsung memanipulasi anggota data, yang perlu diubah. Perubahan ini hanya terjadi di dalam kelas basis dan tidak ada perubahan yang perlu dilakukan pada kelas terderivasi. Melakukan lokalisasi perubahan seperti ini merupakan praktek perekayasaaan perangkat lunak yang baik.

Gambar 4.14 Definisi Kelas KaryawanKomisi Menggunakan Fungsi Anggota untuk Memanipulasi Data private

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Gambar 4.14: KaryawanKomisi.cpp
// Definisi fungsi anggota kelas KaryawanKomisi.
#include <iostream>
#include "KaryawanKomisi.h" // definisi kelas KaryawanKomisi
using namespace std;

// konstruktor
KaryawanKomisi::KaryawanKomisi(
    const string &pertama, const string &akhir, const string &ktp,
    double penjualan, double komisi )
    : namaPertama( pertama ), namaAkhir( akhir ), nomorKTP( ktp )
{
  setPenjualanKotor( penjualan ); // memvalidasi dan menyimpan penjualan kotor
  setBesarKomisi( komisi ); // memvalidasi dan menyimpan besar komisi
} // akhir dari konstruktor KaryawanKomisi

// menetapkan nama pertama
void KaryawanKomisi::setNamaPertama( const string &pertama )
{
  namaPertama = pertama; // seharusnya divalidasi
} // akhir dari fungsi setNamaPertama

// mengembalikan nama pertama
string KaryawanKomisi::getNamaPertama() const
{
  return namaPertama;
} // akhir dari fungsi getNamaPertama

// menetapkan nama akhir
void KaryawanKomisi::setNamaAkhir( const string &akhir )
{
  namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir

// mengembalikan nama akhir
string KaryawanKomisi::getNamaAkhir() const
{
  return namaAkhir;
} // akhir dari fungsi getNamaAkhir

// menetapkan nomor kartu penduduk
void KaryawanKomisi::setNomorKTP( const string &ktp )
{
  nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP

// mengembalikan nomor kartu penduduk
string KaryawanKomisi::getNomorKTP() const
{
  return nomorKTP;
} // akhir dari fungsi getNomorKTP

// menetapkan jumlah penjualan kotor
void KaryawanKomisi::setPenjualanKotor( double penjualan )
{
  if ( penjualan >= 0.0 )
    penjualanKotor = penjualan;
  else
    throw invalid_argument( "penjualan kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor

// menghasilkan jumlah penjualan kotor
double KaryawanKomisi::getPenjualanKotor() const
{
  return penjualanKotor;
} // akhir dari fungsi penjualanKotor

// menetapkan besar komisi
void KaryawanKomisi::setBesarKomisi( double komisi )
{
  if ( komisi > 0.0 && komisi < 1.0 )
    besarKomisi = komisi;
  else
    throw invalid_argument( "besar komisi harus di antara > 0.0 dan < 1.0" );
 } // akhir dari fungsi setBesarKomisi

// mengembalikan besar komisi
double KaryawanKomisi::getBesarKomisi() const
{
  return besarKomisi;
} // akhir dari fungsi getBesarKomisi

// menghitung penghasilan
double KaryawanKomisi::penghasilan() const
{
  return getBesarKomisi() * getPenjualanKotor();
} // akhir dari fungsi penghasilan

// menampilkan objek KaryawanKomisi
void KaryawanKomisi::tampil() const
{
  cout << "karyawan komisi: "
    << getNamaPertama() << ' ' << getNamaAkhir()
    << "\nnomor kartu penduduk: " << getNomorKTP()
    << "\npenjualan kotor: " << getPenjualanKotor()
    << "\nbesar komisi: " << getBesarKomisi();
} // akhir dari fungsi tampil

Perubahan pada Definisi Fungsi Kelas KaryawanKomisiPlusPokok
Kelas KaryawanKomisiPlusPokok mewarisi fungsi-fungsi anggota public kelas KaryawanKomisi dan dapat mengakses anggota data private melalui fungsi anggota yang diwarisi. Header KaryawanKomisiPlusPokok tetap tidak berubah dari Gambar 4.10. Kelas ini mengalami perubahan pada implementasi fungsi anggota (Gambar 4.15) yang membedakannya dari versi sebelumnya (Gambar 4.10 - 4.11). Fungsi anggota penghasilan (Gambar 4.15, baris 33-36) dan tampil (baris 39-47) masing-masing memanggil fungsi anggota getGajiPokok untuk mendapatkan nilai gaji pokok, menggantikan pengaksesan gajiPokok secara langsung. Hal ini mengisolasi penghasilan dan tampil dari perubahan yang berpotensi terjadi pada anggota data gajiPokok pada implementasi. Sebagai contoh, jika Anda memutuskan untuk menamai-ulang anggota data gajiPokok atau mengubah tipenya, maka hanya fungsi anggota getGajiPokok dan setGajiPokok yang perlu untuk diubah.

Gambar 4.15 Kelas KaryawanKomisiPlusPokok yang Mewarisi Kelas KaryawanKomisi tetapi tidak bisa secara langsung mengakses data private

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
// Gambar 4.15: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;

// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
    const string &pertama, const string &akhir, const string &ktp,
    double penjualan, double komisi, double gaji )
    // secara eksplisit memanggil konstruktor kelas basis
    : KaryawanKomisi( pertama, akhir, ktp, penjualan, komisi )
{
  setGajiPokok( gaji ); // memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor KaryawanKomisiPlusPokok

// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double gaji )
{
  if ( gaji >= 0.0 )
    gajiPokok = gaji;
  else
    throw invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok

// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
  return gajiPokok;
} // akhir dari fungsi getGajiPokok

// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
  return KaryawanKomisi::penghasilan();
} // akhir dari fungsi penghasilan

// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
  cout << "karyawan komisi bergaji pokok: ";
      
  // memanggil fungsi tampil kelas KaryawanKomisi
  KaryawanKomisi::tampil();
   
  cout << "\ngaji pokok: " << getGajiPokok();
} // akhir dari fungsi tampil

Fungsi Anggota penghasilan Kelas KaryawanKomisiPlusPokok
Fungsi penghasilan pada kelas KaryawanKomisiPlusPokok (Gambar 4.15, baris 33-36) mendefinisikan-ulang fungsi penghasilan kelas KaryawanKomisi (Gambar 4.14, baris 84-87) untuk menghitung penghasilan dari karyawan komisi bergaji pokok. Versi penghasilan pada kelas KaryawanKomisiPlusPokok mendapatkan bagian penghasilan karyawan yang hanya berbasis komisi saja dengan memanggil fungsi penghasilan pada kelas KaryawanKomisi dengan ekspresi KaryawanKomisi::penghasilan() (Gambar 4.15, baris 35). Fungsi penghasilan pada kelas KaryawanKomisiPlusPokok kemudian menambahkan gaji pokok kepada nilai tersebut untuk menghitung total penghasilan karyawan. Perhatikan sintaks yang digunakan untuk memanggil fungsi anggota terdefinisi-ulang pada kelas basis dari kelas terderivasi; yaitu dengan menempatkan nama kelas basis dan operator resolusi skop (::) sebelum nama fungsi anggota kelas basis. Dengan memiliki fungsi penghasilan pada kelas KaryawanKomisiPlusPokok untuk memanggil fungsi anggota penghasilan pada kelas KaryawanKomisi dalam menghitung sebagian dari penghasilan objek KaryawanKomisiPlusPokok, Anda telah terhindar dari praktek penduplikasian kode dan berhasil mereduksi masalah perawatan-kode.

Fungsi Anggota tampil Kelas KaryawanKomisiPlusPokok
Sama halnya, fungsi tampil pada kelas KaryawanKomisiPlusPokok (Gambar 4.15, baris 39-47) mendefinisikan-ulang fungsi tampil pada kelas KaryawanKomisi (Gambar 4.14, baris 90 - 97) untuk menampilkan informasi karyawan komisi bergaji pokok. Versi baru ini menampilkan sebagian dari informasi objek KaryawanKomisiPlusPokok dengan memanggil fungsi anggota tampil pada kelas KaryawanKomisi dengan ekspresi KaryawanKomisi::tampil() (Gambar 4.15, baris 44). Fungsi tampil pada kelas KaryawanKomisiPlusPokok kemudian menampilkan sisa informasi objek KaryawanKomisiPlusPokok yang lain.

Kesimpulan
*      Ketika menciptakan sebuah kelas, daripada menulis anggota data dan anggota fungsi yang baru, Anda bisa menciptakan kelas baru yang mewarisi anggota-anggota dari kelas yang sudah ada. Kelas yang sudah ada ini disebut dengan kelas basis, dan kelas baru yang mewarisi tersebut dikenal dengan kelas terderivasi. Bahasa pemrograman lain seperti Java dan C# menyebutkan kelas basis sebagai superkelas dan kelas terderivasi sebagai subkelas. Kelas terderivasi merepresentasikan grup-grup objek yang lebih spesifik.
*      Karena setiap objek kelas terderivasi merupakan objek kelas basisnya, dan satu kelas basis dapat memiliki banyak kelas terderivasi, maka himpunan objek yang direpresentasikan oleh kelas basis umumnya lebih besar atau lebih umum dari himpunan objek yang direpresentasikan oleh sembarang kelas terderivasinya.
*      Anggota public suatu kelas basis dapat diakses dari dalam tubuh kelas tersebut dan dari tempat manapun yang dapat dilakukan program (misalnya lewat nama, referensi, atau pointer) di dalam kelas basis tersebut atau dari salah satu kelas terderivasinya.Anggota private suatu kelas basis dapat diakses dari dalam tubuh kelas tersebut dan oleh friend dari kelas basis tersebut. Pada bagian ini, akan dikenalkan penspesifikasi akses protected. Penggunaan akses protected menawarkan level proteksi menengah antara akses public dan private. Anggota protected suatu kelas basis dapat diakses dari dalam tubuh kelas basis tersebut, oleh anggota dan friend dari kelas basis tersebut, dan oleh anggota dan friend dari sembarang kelas yang diderivasi dari kelas basis tersebut.

Latihan
1)      Banyak program yang ditulis dengan pewarisan dapat ditulis dengan kompsosisi, dan sebaliknya. Tulis-ulanglah kelas KaryawanKomisiPlusPokok pada hirarkri KaryawanKomisi-KaryawanKomisiPlusPokok menggunakan komposisi menggantikan pewarisan. Setelah Anda melakukannya, nilailah aspek kecocokan atas dua pendekatan (pewarisan dan komposisi) tersebut. Pendekatan manakah yang lebih bagus? Mengapa?
2)      Gambarlah hirarki pewarisan untuk mahasiswa di suatu universitas yang sama dengan hirarki pada Gambar 4.2. Gunakan Mahasiswa sebagai kelas basis hirarki, kemudian cantumkan kelas MahasiswaSarjana dan kelas MahasiswaPascaSarjana yang mewarisi dari Mahasiswa. Lanjutkan untuk memperluas hirarki sedalam dan sebanyak mungkin level yang Anda bisa. Sebagai contoh, Yunior dan Senior dapat mewarisi kelas MahasiswaSarjana, dan MahasiswaMaster dan MahasiswaDoktor dapat mewarisi kelas MahasiswaPascaSarjana. Setelah menggambar hirarki, diskusikan relasi yang eksis di antara kelas. Selanjutnya, realisasikan hirarki pewarisan tersebut dengan kode C++.

3)      Tulislah sebanyak mungkin jenis bangun yang bisa Anda pikirkan baik bangun dua dimensi maupun bangun tiga dimensi. Formasikan semuanya ke dalam hirarki Bangun menjadi sebanyak mungkin level yang Anda bisa. Hirarki Anda harus memiliki kelas bangun Bangun yang mewarisi kelas BangunDuaDimensi dan BangunTigaDimensi. Setelah menggambar hirarki, diskusikan relasi yang eksis di antara kelas. Selanjutnya, realisasikan hirarki pewarisan tersebut dengan kode C++.


No comments:

Post a Comment