Saturday, October 7, 2017

Kuliah 3 C++: Kelas dan Objek



BAB 3.
Kelas dan Objek






3.1 Fungsi Friend untuk Sebuah Kelas
Fungsi friend untuk sebuah kelas memiliki akses terhadap semua anggota kelas baik private, terproteksi, atau publik dan karakteristik ini membuat fungsi friend berguna pada banyak aplikasi, khususnya pada pembebanan operator. Namun, akses bebas terhadap semua anggota dari suatu kelas juga melanggar kapabilitas penyimpanan informasi dari kelas. Karena pertemanan dijamin oleh kelas, oleh karena itu, deklarasi kelas harus memuat deklarasi bahwa fungsi itu friend (teman) dari kelas itu. Selain itu, fungsi friend bukanlah fungsi anggota dari kelas dimana di dalamnya ia dideklarasikan sebagai friend. Jadi, fungsi friend didefinisikan di luar tubuh kelas. Deklarasi atas prototipe dari sebuah fungsi friend di dalam tubuh kelas diilustrasikan berikut. Pendeklarasiannya diawali dengan katakunci friend yang diikuti dengan tipe data dari fungsi dan pengenal (nama) fungsi yang diikuti dengan suatu daftar tipe parameter fungsi yang diapit di dalam kurung (). Kemudian pendeklarasian diakhiri dengan semikolon.

friend tipe pengenal(tipe_parameter1, tipe_parameter2, …);

Sebagai contoh, sebuah fungsi dengan nama Luas() dideklarasikan sebagai sebuah fungsi friend dari kelas Rekt yang merupakan sebuah kelas untuk bangun-bangun rektangular yang memiliki sisi-sisi x dan y berikut.

friend int Luas(const Rekt &b);

Pada deklarasi tersebut, data objek b dari kelas Rekt merupakan satu-satunya parameter fungsi. Definisi dari fungsi friend diberikan di luar tubuh kelas. Fungsi tersebut didefinisikan sebagai berikut.

int Luas(const Rekt &b)
{return b.x * b.y ;}

Pada definisi tersebut, operator resolusi skop (::) tidak digunakan karena fungsi Luas() bukanlah fungsi anggota dari kelas.

Hal-hal berikut perlu diperhatikan terkait dengan fungsi friend untuk sebuah kelas.
  1. Jika sebuah fungsi F adalah fungsi friend untuk kelas B, maka F dapat mengakses semua anggotadari kelas B.
  2. Pertemanan dijamin oleh kelas. Oleh karena itu, fungsi friend harus dideklarasikan di dalam tubuh kelas seperti yang telah dijelaskan.
  3. Prototipe fungsi dari fungsi friend yang diawali dengan katakunci friend dideklarasikan di dalam tubuh kelas tetapi fungsi tersebut didefinisikan di luar tubuh kelas.
  4. Fungsi friend bukanlah fungsi anggota dari kelas yang menjadi temannya. Oleh karena itu, operator resolusi skop tidak diperlukan ketika mendefinisikan fungsi friend di luar tubuh kelas.
  5. Sebuah kelas dapat memiliki sebanyak mungkin fungsi friend. Dan sebuah fungsi friend dapat memiliki 
  6. Sebuah fungsi friend dapat dideklarasikan di mana pun di dalam kelas. Penspesifikasi akses, yaitu public, protected, atau private, tidak memengaruhi fungsi friend.

Program berikut mengilustrasikan pendeklarasian dan pendefinisian suatu fungsi friend.

Program 3.1 Mengilustrasikan pendefinisian fungsi friend

#include <iostream>
using namespace std;

class Rekt{
   friend int Luas(const Rekt &a);              //fungsi friend Luas()

   int x,y; // private secara default

   public:
      Rekt(int L, int W){x = L, y = W;}         //fungsi konstruktor
}; //akhir dari kelas Rekt

int Luas (const Rekt &b)   //definisi dari fungsi friend
{
   return b.x*b.y;         //operator resolusi skop tidak diperlukan
};

int main()
{
   Rekt R1(5,6), R2(3,4) ; //deklarasi atas dua objek R1 dan R2

   cout<<"Luas Dari R1 = "<<Luas(R1)<<"\n";
   cout<<"Luas dari R2 = "<<Luas(R2)<<"\n";

   return 0 ;
}
KELUARAN
Luas Dari R1 = 30
Luas dari R2 = 12
       

Pada program tersebut, fungsi friend mengambil semua argumen dari data objek kelas. Salah satu objek memiliki dimensi 5 dan 6, fungsi friend menghasilkan luas 30 sedangkan objek kedua R2 memiliki dimensi 3 dan 4 dan luasnya dihasilkan sebesar 12. Keluaran program menunjukkan bahwa fungsi friend dapat mengakses anggota-anggota data private dari kelas.

Sebuah kelas dapat mempunyai sebanyak mungkin fungsi friend. Pada program berikut, dua fungsi friend dideklarasikan untuk kelas Rekt. Fungsi friend pertama menghitung luas, yang memerlukan data private dari objek. Fungsi friend kedua menghitung biaya perlakuan terhadap permukaan luasan persegi-panjang.

Program 3.2 Mengilustrasikan sebuah kelas yang memiliki lebih dari satu fungsi friend

#include <iostream>
using namespace std;

class Rekt{
   friend int Luas(const Rekt &a); //sebuah fungsi friend
   int x,y; //private secara default

   public:
      Rekt(int L, int W){x = L, y = W;} //fungsi konstruktor
      friend double Biaya(const Rekt &a, double);
      //fungsi friend kedua
}; //akhir dari kelas Rekt

int Luas(const Rekt &b)           //definisi dari fungsi Luas()
{
   return b.x*b.y;
}

double Biaya(const Rekt &b, double s)    //definisi dari fungs Biaya()
{
   return b.x*b.y * s;
}

int main()
{
   double A = 4.5, B = 5.2; // A dan B untuk data untuk fungsi Biaya()
   Rekt R1(10,5), R2(20,5) ;      // R1, R2 adalah dua objek

   cout<<"Luas dari R1 = "<<Luas(R1)<<"\n";
   cout<<"Luas dari R2 = "<<Luas(R2)<<"\n";

   cout<<"Biaya = "<<Biaya(R1,A)<<"\n";
   cout<<"Biaya = "<<Biaya(R2,B)<<"\n";

   return 0 ;
}
KELUARAN
Luas dari R1 = 50
Luas dari R2 = 100
Biaya = 225
Biaya = 520


SATU FUNGSI FRIEND UNTUK BANYAK KELAS
Sebuah fungsi dapat menjadi friend untuk banyak kelas. Ini diilustrasikan pada program berikut dimana di dalamnya fungsi Tampil() dideklarasikan friend untuk dua kelas, yaitu kelas Persegi dan kelas Rekt.

Program 3.3 Mengilustrasikan sebuah fungsi friend untuk lebih dari satu kelas

#include <iostream>
using namespace std;

class Persegi;       //pra-deklearasi dari kelas
class Rekt {  //kelas Rekt
   int x,y;   //private secara default

   public:
   Rekt(int A, int B) {x = A, y = B;}

   int Luas()
   {return x*y;}

   friend void Tampil(Rekt R, Persegi S); //fungsi friend untuk Rekt
}; //akhir dari kelas Rekt

class Persegi { //kelas Persegi
   int sisi;  //private secara default

   public:
      Persegi (int C){sisi = C;}

      int Luas ()
      {return sisi*sisi;}

      friend void Tampil(Rekt R, Persegi S); //fungsi friend untuk Persegi
}; //akhir dari kelas Persegi

void Tampil(Rekt R, Persegi S) //definisi dari fungsi friend
{
   cout<<"Luas dari Rektangular = "<<R.Luas()<<endl;
   cout<<"Luas dari Persegi = "<<S.Luas()<< endl;
}

int main()
{
   Rekt R1(10, 5);
   Persegi S1(10);

   Tampil(R1, S1);

   return 0;
}
KELUARAN
Luas dari Rektangular = 50
Luas dari Persegi = 100



3.2 Kelas Friend
Ketika semua atau hampir semua fungsi dari sebuah kelas memerlukan akses terhadap anggota data dan fungsi anggota dari kelas lain, kelas tersebut secara menyeluruh dapat dideklarasikan friend untuk kelas lain itu. Sebagai contoh, jika fungsi-fungsi dari sebuah kelas A memerlukan akses terhadap anggota-anggota publik, private, dan terproteksi dari kelas B, maka kelas A dapat dideklarasikan sebagai friend class A; di dalam tubuh dari kelas B. Seperti Anda ketahui, friend adalah katakunci di dalam C++. Deklarasi tersebut diilustrasikan berikut.

class B
{
   friend class A; //deklarasi bahwa kelas A adalah friend dari kelas B

   private:
      statemen_statemen;

   friend class C; // deklarasi bahwa kelas C adalah friend dari kelas B

   public:
      statemen_statemen_lain;
};


KARAKTERISTIK-KARAKTERISTIK DARI KELAS FRIEND
Karakteristik-karakteristik dari kelas friend berikut perlu diketahui.
  1. Jika kelas A merupakan friend untuk kelas B, maka fungsi-fungsi dari A dapat mengakses semuaanggota dari B.
  2. Jika kelas A merupakan friend untuk kelas B, maka hal itu tidak berarti bahwa B juga friend untuk kelas A. Pertemanan C++ tidak timbal balik atau resiprokal.
  3. Pertemanan dijamin oleh kelas yang anggota-anggotanya akan diakses. Jika kelas A adalah friend untuk kelas B, maka kelas A harus dideklarasikan di dalam definisi dari kelas B.
  4. Jika kelas A adalah friend untuk kelas B dan kelas B adalah friend untuk kelas C, maka hal itu tidak berarti bahwa kelas A juga friend untuk kelas C atau kelas B adalah friend untuk kelas A atau kelas C adalah friend untuk kelas B atau kelas A. Pertemanan dalam C++ tidak ditransmisikan dan tidak timbal-balik.
  5. Sebuah kelas dapat menjadi friend untuk lebih dari satu kelas. Dan sebuah kelas dapat memiliki lebih dari satu kelas friend.
Pada program berikut, Anda mendefinisikan sebuah kelas Kubik untuk komponen-komponen prismatis dengan dasar rektangular. Kelas memiliki dua fungsi untuk menghitung volume dan luas permukaan eksternal dari elemen-elemen kubikel. Kelas kedua dengan nama Lukis didefinisikan. Kelas ini mempunyai sebuah fungsi untuk menghitung biaya pelukisan permukaan eksternal dari objek-objek kelas Kubik. Kelas Lukis dideklarasikan sebagai friend untuk kelas Kubik.

Program 3.4 Mengilustrasikan deklarasi sebuah kelas friend untuk suatu kelas

#include <iostream>
using namespace std;

class Kubik {
   friend class Lukis; //deklarasi dari kelas friend

   public:
      void sisi2(int , int, int);
      int Luas();
      int volume();

      int x, y, z;
}; //akhir dari kelas Kubik

void Kubik::sisi2(int L, int W, int H)
{x = L, y = W,z = H; } //pengaturan sisi-sisi dari Kubik

int Kubik::Luas()          //definisi dari Luas()
{return 2*(x*y +y*z +z*x);}

int Kubik::volume()        //definisi dari volume()
{return x*y*z ;}

class Lukis{ //deklarasi dari kelas friend Lukis
   private:
      int R;

   public:
      Lukis() {R = 1;}            //konstruktor default
      Lukis(int S) {R = S;} //konstruktor parametris

      Kubik C; // C adalah objek dari kelas Kubik
     
      int Luas (){return C.Luas ();}
      int biaya(int R , Kubik C )
      {return R* C.Luas ();}            
}; //akhir dari kelas Lukis

int main()
{
   Kubik C1 ; //C1 adalah objek dari kelas Kubik
   C1.sisi2 (5,6,5 );

   Lukis P1 ; //P1 adalah objek dari kelas Lukis
   int k = 4;

   cout<<"Volume dari C1 = "<<C1.volume()<<"\n";
   cout<<"Luas permukaan dari C1 = "<<C1.Luas()<<"\n";

   cout<<"Biaya pelukisan P1 = "<<P1.biaya(k, C1)<<"\n";

   return 0 ;
}
KELUARAN
Volume dari C1 = 150
Luas permukaan dari C1 = 170
Biaya pelukisan P1 = 680



3.3 Pointer (Menunjuk) Ke Sebuah Kelas
Pointer ke sebuah kelas dapat dideklarasikan dengan cara yang sama dengan apa dilakukan terhadap variabel integer atau double. Dimisalkan bahwa Anda memiliki sebuah kelas dengan nama List dan dimisalkan bahwa L1 adalah sebuah objek dari kelas itu. Dimisalkan juga bahwa ptr adalah sebuah pointer yang menunjuk kelas List. Untuk deklarasi pointer ke List, Anda bisa menggunakan kode berikut.

List L1;             //deklarasi bahwa L1 adalah objek dari List
List *ptr;           //deklarasi pointer ke List
ptr = &(List) L1;    //penugasan nilai kepada ptr

Baris terakhir dapat pula dituliskan dengan ptr = &List (L1);. Program berikut memberikan ilustrasi dari pointer ke kelas.

Program 3.5 Mengilustrasikan definisi dari pointer yang menunjuk ke sebuah kelas

#include <iostream>
using namespace std;

class List
{
   private:
      int x,y;       //x = jumlah item, y = harga per tem

   public:
      void Setdata(int a, int b) //fungsi publik untuk mengakses x, y
      {
         cout<<"Masukkan jumlah item: "; cin>>a;
         cout<<"Masukkan harga per item: "; cin>>b;
         x = a, y = b;
      }

      void Tampil1()
         {cout<<"Jumlah item = "<<x<<endl;}

      void Tampil2()
         {cout<<"Harga per item = "<<y<<endl;}

      void Tampil3()
         {cout<<"Biaya dari "<<x<<" buah item dengan harga "<<y<<" per item = "<<x*y<<endl;}
}; //akhir dari kelas List

void main()
{
   List L1;
   List *ptr;              //pointer ke List
   ptr = &(List) L1;       //menugaskan alamat dari objek kelas

   int i,j;
   (*ptr).Setdata(i,j);    //nilai-nilai ditugaskan oleh user
  
   ptr -> Tampil1();       // (*ptr) dan ptr-> ekivalen
   ptr -> Tampil2();
   (*ptr).Tampil3();
}
KELUARAN
Masukkan jumlah item: 45
Masukkan harga per item: 54
Jumlah item = 45
Harga per item = 54
Biaya dari 45 buah item dengan harga 54 per item = 2430


Program tersebut juga menunjukkan bahwa untuk memanggil suatu fungsi kelas di dalam main() melalui sebuah pointer ptr, salah satu dari kedua kode berikut dapat digunakan.

ptr -> Tampil3();
atau
(*ptr).Tampil3();

Kedua statemen tersebut ekivalen. Pada statemen kedua, *ptr harus ditempatkan di dalam kurung karena operator dot (.) memiliki keutamaan yang lebih tinggi daripada operator dereferensi (*). Program berikut mengilustrasikan bagaimana fungsi-fungsi berelasi ke objek kedua dari kelas yang sama dapat dipanggil dengan menggunakan operator inkremen (++) pada pointer kelas yang menunjuk ke objek pertama dari kelas. Kedua objek harus dideklarasikan sebelum operator inkremen.

Program 3.6 Mengilustrasikan penginkremenan pointer ke objek kelas pertama menghasilkan pointer ke objek kedua

#include <iostream>
using namespace std;

class List{
   private:
      int x, y, z;

   public:
      void Tampil1()
         {cout<<"Selamat datang ke pasar ini"<<endl;}

      void set_harga(int a, int b, int c)
         {x = a, y = b, z = c;}

      void Tampil2()
      {
         cout<<"Harga dari item1 = "<<x<<endl;
         cout<<"Harga dari item2 = "<<y<<endl;
         cout<<"Harga dari item3 = "<<z<<endl;
      }
}; //akhir dari kelas List

void main()
{
   List L1;
   List *ptr;                            //pointer ke List
   ptr = &(List) L1;              //penugasan alamat dari L1 kepada pointer

   ptr -> set_harga(6, 8, 10);    //fungsi yang berelasi dengan L1
   ptr -> Tampil1();

   cout<<"Daftar Harga 1"<<endl;
   ptr ->Tampil2();

   List L2;          //L2 adalah objek kedua dari kelas
   *ptr++;           //penginkremenan pointer ke L1 menghasilkan pointer ke L2.

   ptr -> set_harga(32,27,38); //fungsi yang berelasi dengan L2.
   ptr -> Tampil1();

   cout<<"Daftar Harga 2"<<endl;
   ptr -> Tampil2();
}
KELUARAN
Selamat datang ke pasar ini
Daftar Harga 1
Harga dari item1 = 6
Harga dari item2 = 8
Harga dari item3 = 10
Selamat datang ke pasar ini
Daftar Harga 2
Harga dari item1 = 32
Harga dari item2 = 27
Harga dari item3 = 38


Pada program di atas, pointer ptr dideklarasikan sebagai pointer yang menunjuk ke kelas List dengan L1 sebagai salah satu objeknya. Fungsi set_harga() dan Tampil() dipanggil. Terlihat bahwa pemanggilan kedua fungsi ini adalah untuk objek L1. Kemudian sebuah objek kedua L2 dideklarasikan dan ptr diinkremen. Penginkremenan menyebabkan ptr menunjuk ke objek kedua L2. Fungsi set_harga() dan Tampil() dipanggil untuk L2 menggunakan pointer tersebut.



3.4 Pointer (Menunjuk) Ke Objek dari Sebuah Kelas
Dimisalkan bahwa L1 adalah sebuah objek dari kelas List, pointer yang menunjuk ke L1 dapat dideklarasikan dan ditugaskan sebagai berikut.

List *ptr = &L1;

Program 3.7 Mengilustrasikan pendefinisian pointer yang menunjuk ke sebuah objek kelas

#include <iostream>
using namespace std;

class List{
   private:
      int x, y, z;

   public:
      List (int a, int b, int c) {x = a, y = b, z = c;} //konstruktor

      void Tampil()
         {
         cout<<"Harga dari item 1 = "<<x<<endl;
         cout<<"Harga dari item 2 = "<<y<<endl;
         cout<<"Harga dari item 3 = "<<z<<endl;
         }
}; //akhir dari kelas List

void main()
{
   int n = 0;

   List L1 (12, 15, 27);
   cout<<"List "<<++n<<endl;
   List *ptr = &L1;        //(*ptr) dan ptr-> ekivalen
   ptr -> Tampil();

   cout<<"\nList"<< ++n <<"\n";
   List L2(30, 54, 60);
   ptr = & L2 ;
   (*ptr).Tampil();
}
KELUARAN
List 1
Harga dari item 1 = 12
Harga dari item 2 = 15
Harga dari item 3 = 27

List2
Harga dari item 1 = 30
Harga dari item 2 = 54
Harga dari item 3 = 60



3.5 Pointer (Menunjuk) Ke Fungsi Anggota Kelas
Deklarasi dan penugasan pointer kepada fungsi anggota dari kelas diilustrasikan berikut.

tipe (nama_kelas ::*nama_pointer)(tipe_parameter) = &nama_kelas :: nama_fungsi;

Pada sintaksis tersebut, kata pertama tipe menandakan tipe data dari nilai balik dari fungsi, yang diikuti dengan (dalam kurung) pengenal kelas, operator resolusi skop dan operator indireksi (*) dan pengenal pointer. Penugasan (sisi kanan dari =) operator alamat & yang diikuti dengan nama kelas, operator resolusi skop, dan diakhiri dengan semikolon atau titik-koma. Pada program 3.7 yang diberikan berikut, Anda memiliki sebuah fungsi dengan nama set_sisi(), sebuah fungsi publik dari kelas Rekt untuk inisialisasi sisi-sisi dari persegi-panjang, yang didefinisikan berikut.

void set_sisi(int L, int W ){x = L , y = W;}

Pointer *ptrSet yang menunjuk ke fungsi ini dideklarasikan dan ditugaskan sebagai berikut.

void (Rekt:: *ptrSet)(int, int) = &Rekt :: set_sisi;

Untuk memanggil fungsi ini untuk sebuah objek R1 dengan panjang 20 dan lebar 15, Anda bisa menuliskan kode berikut.

(R1.*ptrSet)(20, 15);

Program berikut mengilustrasikan penggunaan pointer yang menunjuk ke sebuah fungsi anggota dari kelas.

Program 3.8 Mengilustrasikan pendefinisian pointer yang menunjuk ke sebuah objek kelas

#include <iostream>
using namespace std;

class Rekt {
   int x, y;  //private secara default

   public:
      void set_sisi(int L, int W){x = L, y = W;}
      int Luas() //definisi dari fungsi Luas()
      {
         return x*y;
      }
}; //akhir dari kelas Rekt

int main()
{
   Rekt R1, R2, R3;
   void (Rekt:: *ptrSet)(int,int) = & Rekt :: set_sisi;

   (R1.*ptrSet) (20,15);
   cout<<"Luas dari R1 = "<<R1.Luas()<<endl;

   (R2.*ptrSet) (20,30);   //objek R2 memanggil fungsi dengan pointer
   cout<<"Luas dari R2 = "<<R2.Luas()<<endl;

   Rekt *ptr3 = &R3;       // declaring pointer to object R3 of class

  (ptr3 ->*ptrSet)(16,10); //memanggil fungsi dengan pointer yang menunjuk ke objek
   cout<<"Luas dari R3 = "<<R3.Luas()<<endl;

   return 0 ;
}
KELUARAN
Luas dari R1 = 300
Luas dari R2 = 600
Luas dari R3 = 160



3.6 Pointer (Menunjuk) Ke Anggota Data dari Kelas
Sintaksis untuk pendeklarasian dan penugasan pointer untuk menunjuk ke anggota data adalah sebagai berikut

tipe nama_kelas :: *nama_pointer = & nama_kelas :: nama_data;

Sebagai contoh, sebuah kelas dengan nama Rekt yang memiliki anggota-anggota data int x dan int y, pointer ptrx dan ptry yang menunjuk ke anggota-anggota data dideklarasikan sebagai berikut.

int Rekt :: *ptrx = &Rekt :: x;
int Rekt :: *ptry = &Rekt :: y;

Aplikasi diilustrasikan pada program berikut.

Program 3.9 Mengilustrasikan pendefinisian pointer-pointer yang menunjuk ke anggota data dari kelas

#include <iostream>
using namespace std;

class Rekt{
   friend int Luas(Rekt a); //fungsi friend
   int x, y; //anggota-anggot data private secara default

   public:
      friend double biaya(Rekt a, double);      //fungsi friend lain
      Rekt (int L, int W){x = L,y = W;}         //konstruktor
}; //akhir dari kelas Rekt

int Luas (Rekt b) //definisi dari fungsi Luas() menggunakan pointer
{
   int Rekt :: *ptrx = &Rekt :: x; //ptrx adalah pointer untuk x
   int Rekt :: *ptry = &Rekt :: y; //ptry adalah pointer untuk y
   Rekt *ptrb = &b; //ptrb adalah pointer yang menunjuk ke b

   return b.*ptrx * b.*ptry;
};

double biaya(Rekt b , double m)
{
   return b. x* b. y * m;
}

int main()
{
   double n = 4.5;

   Rekt R1(5,6), R2(3,4);

   cout<<"Luas of R1 = "<<Luas(Rekt(R1))<<"\n";
   cout<<"Luas of R2 = "<<Luas(Rekt(R2))<<"\n";
   cout<<"biaya for R1 = "<<biaya(Rekt(R1),n)<<"\n";

   return 0 ;
}
KELUARAN
Luas of R1 = 30
Luas of R2 = 12
biaya for R1 = 135



3.7 Mengakses Data Private dari Objek Melalui Pointer
Data private dari sebuah objek dapat diakses melalui pointer jika terdapat satu anggota publik. Ini memungkinkan karena anggota-anggota data publik dan anggota-anggota data private dari suatu objek disimpan pada blok-blok memori sekuensial. Jika Anda mengetahui alamat dari satu anggota data, maka Anda dapat menentukan nilai dari anggota-anggota data lain dengan menginkremen atau mendekremen pointer. Hal ini diilustrasikan pada program berikut. Pada program, Anda juga mencari alamat dari data publik dan data private dengan mendapatkan nilai-nilai dari pointer terdekremen. Namun, jika Anda mencoba menentukan alamat dari data private secara langsung dengan menggunakan &L1.z pada program, maka hasilnya akan berupa pesan error.

Program 3.10 Mengilustrasikan pengaksesan data private dari sebuah objek menggunakan pointer

#include <iostream>
using namespace std;

class List{
   private:
      int x, y, z;

   public:
      int Alfa;
      List (int a, int b, int c) {x = a, y = b, z = c;} //konstruktor
}; //akhir dari kelas List

void main()
{
   List L1(10, 20, 30);
   int *pAlfa;                    //pointer ke suatu integer

   L1. Alfa = 50;
   pAlfa = & L1.Alfa;      //penugasan nilai kepada pointer

   cout<<"Alfa = "<<*pAlfa<< endl;
   cout<<"Alamat dari Alfa = "<<pAlfa<< endl;

   pAlfa--;                       //mendekremen pointer untuk mendapatkan z
   cout<<"Data z dari L1 = "<<*pAlfa <<endl;
   cout<<"Alamat dari z = "<<pAlfa<<endl;

   pAlfa--;                       //mendekremen pointer untuk mendapatkan y
   cout<<"Data y dari L1 = "<<*pAlfa <<endl;
   cout<<"Alamat dari y = "<<pAlfa<<endl;
  
   pAlfa--;                       //mendekremen pointer untuk mendapatkan x
   cout<<"Data x dari L1 = "<<*pAlfa <<endl;
   cout<<"Alamat dari x = "<<pAlfa<<endl;
}
KELUARAN
Alfa = 50
Alamat dari Alfa = 0018FF44
Data z dari L1 = 30
Alamat dari z = 0018FF40
Data y dari L1 = 20
Alamat dari y = 0018FF3C
Data x dari L1 = 10
Alamat dari x = 0018FF38


Pada program berikut, Anda akan mengawalinya dari alamat objek. Alamat objek merupakan alamat dari data pertama pada objek.

Program 3.11 Mengilustrasikan pengaksesan data private dari alamat objek

#include <iostream>
using namespace std;

class List{
   private:
      int x, y, z;

   public:
      int s;
      List(int a, int b, int c) {x = a, y = b, z = c;} //konstruktor
}; //akhir dari kelas List

void main()
{
   List L1( 10, 20 , 30); ;
   L1.s = 40;
   int *ptrL1 ;

   ptrL1 = (int*)& L1 ;
   cout<<"Nilai dari x = "<<*ptrL1<<endl;
   cout<<"Alamat dari x = "<<ptrL1<<endl;

   ptrL1++;
   cout<<"Data y dari L1 = "<<*ptrL1<<endl;
   cout<<"Alamat dari y = "<<ptrL1<<endl;

   ptrL1++;
   cout<<"Data z dari L1 = "<<*ptrL1<<endl;
   cout<<"Alamat dari z = "<<ptrL1<<endl;

   ptrL1 ++;
   cout<<"Data s dari L1 = "<<*ptrL1<<endl;
   cout<<"Alamat dari s = "<<ptrL1<<endl;
}
KELUARAN
Nilai dari x = 10
Alamat dari x = 0018FF38
Data y dari L1 = 20
Alamat dari y = 0018FF3C
Data z dari L1 = 30
Alamat dari z = 0018FF40
Data s dari L1 = 40
Alamat dari s = 0018FF44

Nilai dari pointer ptrL1 merupakan alamat dari data pertama yang merupakan alamat dari x. Dengan menginkremen pointer ini, Anda akan mendapatkan pointer yang menunjuk ke data kedua, yaitu y. Dengan melakukan hal yang sama, Anda akan mendapatkan pointer yang menunjuk ke data ketiga, yaitu z.



3.8 Pointer this
Kata this merupakan katakunci dalam C++ dan merupakan nama pointer yang menunjuk ke suatu objek kelas. Ketika sebuah objek diciptakan, kompiler menciptakan pointer this yang menjejak alamat dari objek itu. Pointer this bukanlah bagian dari objek tetap objek dapat mengaksesnya atau Anda dapat mengatakan bahwa sebuah objek dapat mengakses alamatnya sendiri. Ketika objek memanggil sebuah fungsi anggota kelas, pointer this menjadi argumen implisit dari fungsi dan fungsi tersebut memproses data objek.

Pada program berikut, this dan *this digunakan pada konstruktor kelas. Selain itu, Anda mencari nilai dari pointer this untuk dua objek C1 dan C2. Anda juga mencari alamat dari objek C1 dan C2 menggunakan operator alamat &. Nilai pointer this untuk kedua objek sama dengan alamat-alamatnya.

Program 3.12 Mengilustrasikan aplikasi dari pointer this

#include <iostream>
using namespace std;

class Kubik {
   public:
      Kubik(int L, int W, int H){this ->x=L, (*this).y=W, this->z=H;}
      //fungsi di atas adalah konstruktor

      int luas_permukaan();
      int volume();

      void Tampil1() // Displays private data of object.
      {
         cout<<"x = "<<this->x<<", y = "<<this->y<<", z = "
             <<(*this).z <<endl;
      }

      void Tampil2()
      {cout << this<<endl;} //menghasilkan nilai dari this

   private:
      int x, y, z;                //data private
}; //akhir dari kelas Kubik

int Kubik::luas_permukaan() //definisi dari luas_permukaan()
{
   return 2*(x*y +y*z +z*x);
}

int Kubik::volume()               //definisi dari volume()
{
   return x*y*z;
}

int main()
{
   Kubik C1(5,6,4), C2(7,8,5) ; //C1 dan C2 adalah objek dari Kubik

   C1.Tampil1();
   C1.Tampil2();           //nilai dari pointer this untuk C1

   cout<<&C1<<endl;        //alamat dari C1
   C2.Tampil1();
   C2.Tampil2();           //nilai dari pointer this untuk C2
   cout<<&C2<<endl;        //alamat dari C2

   cout<<"Volume dari Kubik C1 = "<<C1.volume()<<"\n";
   cout<<"Volume dari Kubik C2 = "<<C2.volume()<<"\n";

   cout<<"Luas permukaan dari C1 = "<<C1.luas_permukaan()<<"\n";
   cout<<"Luas permukaan dari C2 = "<<C2.luas_permukaan()<<"\n";

   return 0 ;
}
KELUARAN
x = 5, y = 6, z = 4
0018FF3C
0018FF3C
x = 7, y = 8, z = 5
0018FF30
0018FF30
Volume dari Kubik C1 = 120
Volume dari Kubik C2 = 280
Luas permukaan dari C1 = 148
Luas permukaan dari C2 = 262

Dari keluaran program, terlihat jelas bahwa nilai dari pointer this dan alamat dari objek-objek adalah sama. Selain itu, statemen (*this).z dipakai untuk menentukan nilai dari data z dari objek. Pointer this menunjuk ke objek kelas.



3.9 Anggota Data Statis dari Kelas
Objek-objek dari suatu kelas memiliki salinan sendiri atas anggota-anggota data dari kelas. Pada beberapa situasi tertentu, sejumlah data bisa jadi sama untuk semua objek kelas. Pada kasus itu, daripada setiap objek memiliki salinan sendiri dari data objek, akan lebih mudah bila hanya ada satu salinan data yang dipakai bersama oleh semua objek kelas, karena ini akan menghemat memori, khususnya ketika data yang dipakai bersama itu cukup besar. Untuk aplikasi semacam itu, data bersama itu perlu dideklarasikan static. Data statis dapat dideklarasikan bersamaan dengan salah satu dari ketiga penspesifikasi akses, yaitu public, protected, atau private. Data statis publik dapat diakses secara langsung oleh setiap objek kelas karena data statis dipakai bersama oleh semua objek. Anggota data statis yang dideklarasikan private atau terproteksi dapat diakses melalui fungsi-fungsi publik dari kelas.

Pendeklarasian data statis diawali dengan katakunci static. Hal ini diilustrasikan oleh program berikut.

Program 3.13 Mengilustrasikan pendeklarasian anggota statis di dalam sebuah kelas

#include <iostream>
using namespace std;

class Kubik{
   public:
      static int x; //x dideklarasikan static
      Kubik(int W ): y(W) {}      //konstruktor

      static void Tampil()        //fungsi statis
      {
         cout<<"Tinggi dari semua objek adalah = "<<z<<endl;
      }
      int luas_permukaan();
      int volume();

   private:
      int y;
      static int z; //variabel statis
}; //akhir dari kelas Kubik

int Kubik :: x = 10;
int Kubik :: z = 5;

int Kubik::luas_permukaan()
{
   return 2*(x*y +y*z +z*x);
}

int Kubik::volume()
{
   return x*y*z;
}

int main()
{
   Kubik C1(6), C2(3);

   cout<<"C1.x = "<<C1.x<<", C2.x = "<<C2.x <<endl;
   Kubik::Tampil(); //pemanggilan fungsi tanpa objek

   cout<<"Volume dari Kubik C1 " <<C1.volume()<<"\n";
   cout<<"Volume dari Kubik C2 = "<<C2.volume()<<"\n";

   cout<<"Luas permukaan dari C1 = "<<C1.luas_permukaan()<<"\n";
   cout<<"Luas permukaan dari C2 = "<<C2.luas_permukaan()<<"\n";

   return 0 ;
}
KELUARAN
C1.x = 10, C2.x = 10
Tinggi dari semua objek adalah = 5
Volume dari Kubik C1 300
Volume dari Kubik C2 = 150
Luas permukaan dari C1 = 280
Luas permukaan dari C2 = 190

Pada program di atas, dua anggota data x dan z dideklarasikan static. Variabel int x dideklarasikan static di bawah domain publik sedangkan variabel int z dideklarasikan static di bawah domain private. Data x (sebuah anggota publik) dapat diakses secara langsung oleh objek kelas. Lihat keluaran C1.x = 10 dan C2.x = 10, pada baris pertama keluaran program. Data statis yang dideklarasikan private tidak dapat diakses secara langsung oleh objek. Ia hanya bisa diakses melalui fungsi publik sama seperti anggota data private biasa. Pada program tersebut, hal ini diilustrasikan oleh fungsi Tampil() yang menampilkan nilai dari z.



3.10 Anggota Fungsi Statis dari Kelas
Anggota fungsi dari suatu kelas dapat pula dideklarasikan static jika argumen-argumennya juga dideklarasikan static atau jika fungsi itu tidak mengakses sembarang anggota tak-statis dari kelas. Pointer this yang berkaitan dengan setiap objek kelas hanya dapat diterapkan pada anggota fungsi tak-statis dari kelas. Anggota fungsi statis dari kelas tidak memiliki pointer this. Program berikut mengilustrasikan aplikasi dari sebuah fungsi statis dengan parameter-parameter statis.

Program 3.14 Mengilustrasikan fungsi anggota statis dari sebuah kelas

#include <iostream>
using namespace std;

class Kubik {
   public:
      Kubik(int H):z(H) {} //konstruktor
      static int luas_dasar(){return x*y;} //fungsi statis
      int luas_permukaan();
      int volume( );

   private:
      static int x , y;    //x dan y dideklarasikan static
      int z ;
}; //akhir dari kelas Kubik

int Kubik :: x = 5; //anggota data statis
int Kubik :: y =8 ; //anggota data statis

int Kubik::luas_permukaan() //definisi dari luas_permukaan()
{
   return 2*(x*y +y*z +z*x);
}

int Kubik::volume()               //definisi dari volume()
{
   return x*y*z;
}

int main()
{
   Kubik C1(5), C2(8) ;

   cout<<"Luas dasar dari semua objek = "<<Kubik::luas_dasar()<<endl;
  
   cout<<"Volume dari Kubik C1 " <<C1.volume()<<"\n";
   cout<<"Volume dari Kubik C2 = "<<C2.volume()<<"\n";

   cout<<"Luas permukaan dari C1 = "<<C1.luas_permukaan()<<"\n";
   cout<<"Luas permukaan dari C2 = "<<C2.luas_permukaan()<<"\n";

   return 0 ;
}
KELUARAN
Luas dasar dari semua objek = 40
Volume dari Kubik C1 200
Volume dari Kubik C2 = 320
Luas permukaan dari C1 = 210
Luas permukaan dari C2 = 288



3.11 Pengelolaan Memori Dinamis Untuk Objek-Objek Kelas
OPERATOR NEW DAN DELETE DAN NEW[] DAN DELETE[]
Operatot new mengalokasikan memori dari tempat penyimpanan bebas yang dinamakan dengan heap sedangkan operator delete melakukan kebalikannya, yang membebaskan memori dengan menghapus objek. Memori yang dibebaskan dikembalikan ke heap untuk kegunaan lain. Untuk pengalokasian memori untuk array, Anda memiliki operator new[] dan operator delete[] untuk menghapus array dan membebaskan memori. Untuk objek-objek kelas, operator new dipakai untuk mengalkasikan memori bagi objek tunggal sedangkan operator new[] dipakai untuk menciptakan sebuah array yang memuat objek-objek. Jadi, objek tunggal dihapus dari memori menggunakan operator delete dan array objek dihapus dengan operator delete[]. Harus diperhatikan bahwa ketika new[] digunakan untuk pengalokasian memori, untuk membebaskan memori Anda perlu menggunakan delete[] dan bukan hanya delete. Sebagai contoh, jika Anda telah menciptakan sebuah array objek menggunakan new[] dan jika Anda hanya menggunakan delete untuk menghapus array, maka operator delete itu hanya menghapus objek pertama dari array dan objek-objek lainnya tidak terhapus. Jadi, pembebasan memori hanya parsial. Program berikut mengilustrasikan aplikasi dari operator new dan delete untuk objek-objek kelas.

Program 3.15 Mengilustrasikan penggunaan operator new dan delete untuk objek kelas

#include <iostream>
using namespace std;

class List{
   private:
      double x ; // x = berat dalam kg, y = harga per kg
      double y;

   public:
      void set_data(double a, double b )
      {x = a; y = b;}

      void Tampil()
      {
         cout<<"Berat = "; cin>>x;
         cout<<"Harga = "; cin>>y;
         cout<<"Harga dari "<<x<<" kg dengan biaya "<<y<<" per kg = "<<x*y<<endl;
      }
};

void main()
{
   double i,j;

   List *ptr= new List ; //menggunakan operator new
   (*ptr).set_data(i,j);

   ptr -> Tampil();    //(*ptr) dan ptr-> ekivalen

   delete ptr;
}
KELUARAN
Berat = 34.5
Harga = 3.3
Harga dari 34.5 kg dengan biaya 3.3 per kg = 113.85

Program berikut mengilustrasikan aplikasi dari new[] dan delete[].

Program 3.16 Mengilustrasikan penggunaan operator new[] dan delete[] untuk array objek

#include <iostream>
using namespace std;

class List {
   private:
      int x,y; //x = jumlah item, y = harga per item

   public:
      void set_data(int a, int b)
      {
         x = a;
         y = b;
      }

      void Tampil()
      {
         cout<<"Jumlah item = "; cin>>x;
         cout<<"Harga tiap item = "; cin>>y;
         cout<<"Biaya dari "<<x<<" buah item dengan harga "<<y<<" per item = "<<x*y<<endl;
      }
}; //akhir dari kelas List

void main()
{
   List *ptr= new List[3]; //pointer ke kelas List

   for (int k=0; k<3; k++)
   {
      cout<<"Untuk nomor item " <<k+1<<endl;
      int i=0,j=0; //user memasukkan data

      (*ptr).set_data(i,j);
      ptr -> Tampil();
   } // (*ptr) dan ptr-> ekivalen

   delete[] ptr;
}
KELUARAN
Untuk nomor item 1
Jumlah item = 34
Harga tiap item = 45
Biaya dari 34 buah item dengan harga 45 per item = 1530
Untuk nomor item 2
Jumlah item = 65
Harga tiap item = 54
Biaya dari 65 buah item dengan harga 54 per item = 3510
Untuk nomor item 3
Jumlah item = 76
Harga tiap item = 76
Biaya dari 76 buah item dengan harga 76 per item = 5776



3.12 Kelas Matriks
Kelas berikut berkaitan dengan matriks. Fungsi-fungsi seperti penjumlahan, pengurangan, atau perkalian matriks dicantumkan di dalam program utama. 

Program 3.17 Mengilustrasikan penjumlahan, pengurangan, dan perkalian matriks

#include <iostream>
using namespace std;

class Matriks
{
   private:
      int m, n;

   public:
      int** Ptr;
      Matriks (int B , int K)
      {
         m = B, n = K ; // B untuk baris dan K untuk kolom
         Ptr = new int *[m];
         for(int i =0; i<m; i++)
            Ptr[i] = new int [n];
      }

      // Nil_E untuk nilai elemen
      void Baca_Elemen()
      {
         cout<<"Masukkan elemen-elemen dari matriks "<<m<<"x"<<n<<": ";
         int Nil_E =0;

         for(int b =0; b< m; b++)
            for (int k =0; k<n;k++)
            {
               cin>>Nil_E;
               Ptr[b][k] = Nil_E;
            }
      }

      void Tulis_Elemen()
      {
         for(int s=0; s<m; s++)
         {
            for(int p=0; p<n; p++)
               cout<<Ptr[s][p]<<"\t ";
            cout<<endl;
         }
      }
};

int main()
{
   Matriks A(3,3), B(3,3), K(3, 3), D(3,3), E(3,3);

   cout<<"Masukkan elemen-elemen dari matriks A dan B.\n";
   A.Baca_Elemen();
   B.Baca_Elemen();

   cout <<"Untuk matriks A, Anda memasukkan elemen-elemen berikut: \n";
   A.Tulis_Elemen( );

   cout <<"Untuk matriks B, Anda memasukkan elemen-elemen berikut: \n";
   B.Tulis_Elemen( );

   cout<<"A.Ptr[1][0] = " << A.Ptr[1][0]<< endl;
   for (int k = 0; k<3; k++ )
      for ( int p =0; p<3; p++)
      {
         K.Ptr[k][p] = A.Ptr[k][p] + B.Ptr[k][p]; //penjumlahan matriks
         D.Ptr[k][p] = A.Ptr[k][p] - B.Ptr[k][p]; //pengurangan matriks
      }

   for(int J = 0; J<3; J++) //perkalian matriks
      for(int K=0; K<3; K++)
      {
         E.Ptr[J][K] = 0;
         for (int S =0; S<3; S++)
            E.Ptr[J][K] += A.Ptr[J][S] * B.Ptr[S][K];
      }

   //Statemen-statemen keluaran
   cout<<"Matriks K = Matriks A + Matriks B: "<<endl;
   cout<<"Elemen-elemen dari matriks K adalah berikut: "<<endl;
   K.Tulis_Elemen();

   cout<<"untuk matriks D = Matriks A - Matriks B :"<<endl;
   cout<<"Elemen-elemen dari matriks D adalah berikut: "<<endl;
   D.Tulis_Elemen();

   cout<<"untuk matriks E = Matriks A * Matriks B :"<<endl;
   cout<<"Elemen-elemen dari matriks E adalah berikut: "<<endl;
   E.Tulis_Elemen();

   return 0;
}
KELUARAN
Masukkan elemen-elemen dari matriks A dan B.
Masukkan elemen-elemen dari matriks 3x3: 1 2 3 4 5 6 7 8 9
Masukkan elemen-elemen dari matriks 3x3: 10 20 30 40 50 60 70 80 90
Untuk matriks A, Anda memasukkan elemen-elemen berikut:
1        2       3
4        5       6
7        8       9
Untuk matriks B, Anda memasukkan elemen-elemen berikut:
10       20      30
40       50      60
70       80      90
A.Ptr[1][0] = 4
Matriks K = Matriks A + Matriks B:
Elemen-elemen dari matriks K adalah berikut:
11       22      33
44       55      66
77       88      99
untuk matriks D = Matriks A - Matriks B :
Elemen-elemen dari matriks D adalah berikut:
-9       -18     -27
-36      -45     -54
-63      -72     -81
untuk matriks E = Matriks A * Matriks B :
Elemen-elemen dari matriks E adalah berikut:
300      360     420
660      810     960
1020     1260    1500


LATIHAN
  1. Apa itu fungsi friend untuk suatu kelas?
  2. Apakah yang menjadi hak dari fungsi friend?
  3. Bagaimana fungsi friend dideklarasikan dan didefinisikan?
  4. Bagaimana mendeklarasikan sebuah kelas friend?
  5. Apa karakteristik-karakteristik dari sebuah kelas friend?
  6. Apa itu anggota data statis dari sebuah kelas?
  7. Apa itu anggoa fungsi statis dari sebuah kelas? Tuliskanlah kode untuk mengilustrasikan pendeklarasian sebuah anggota fungsi statis dari suatu kelas?
  8. Apa perbedaan antara anggota data statis dari sebuah kelas dan anggota data konstan dari suatu kelas?
  9. Bagaimana Anda mendeklarasikan dan menginisialisasi anggota data statis dari suatu kelas?
  10. Apa itu pointer this? Bagaimana pointer itu berelasai dengan objek kelas?
  11. Berikan contoh kode dimana di dalamnya pointer this secara eksplisit digunakan.
  12. Berikan contoh kode yang mendeklarasikan sebuah pointer yang menunjuk ke fungsi anggota dari sebuah kelas.
  13. Bagaimana Anda mendeklarasikan sebuah pointer yang menunjuk ke objek dari sebuah kelas.
  14. Bagaimana Anda mendeklarasikan pointer yang menunjuk ke anggota data dari sebuah kelas? Tuliskan kode untuk mengilustrasikannya.
  15. Fungsi kelas mana yang dipanggil ketika sebuah objek kelas diciptakan dan fungsi mana yang dipanggil untuk menghapusnya?
  16. Apa gunanya operator new dan operator new[]? Tuliskan kode untuk mengilustrasikannya.
  17. Apa yang Anda pahami tentang pengelolaan memori dinamis?
  18. Tuliskan sebuah program yang mengilustrasikan pendeklarasian pointer yang menunjuk ke objek kelas.
  19. Tuliskan sebuah program yang mengilustrasikan pendeklarasian pointer yang menunjuk ke anggota fungsi kelas.
  20. Tuliskan sebuah program yang mengilustrasikan pendeklarasian pointer yang menunjuk ke kelas.


No comments: