Type Casting dan Keyword Virtual

Kalian bisa menggunakan type casting untuk memaksa suatu tipe menjadi tipe lain. Kalian juga bisa menggunakannya untuk mendapatkan data perbyte dari tipe yang ukurannya lebih dari 1 byte. 

Type casting yang ada dalam Bahasa C++, yaitu :
  1. const_cast<type> (expr)
  2. dynamic_cast<type> (expr)
  3. reinterpret_cast<type> (expr)
  4. static_cast<type> (expr)
  5. C-style cast
Saya tidak akan membahas C-style cast yang lebih sering digunakan dalam bahasa C. Saya cuma akan membahas type casting lain yang dikhususkan untuk C++. Kalau kalian mau membaca tentang C-style cast, kalian bisa membacanya di tulisan saya yang lain.

Static_cast

Static_cast adalah type casting paling sederhana dan paling aman karena ada pengecekannya saat dicompile. Static_cast hanya bisa digunakan untuk mengubah tipe data menjadi tipe data tujuan yang "punya kesamaan". Penggunaan static_cast untuk pointer mungkin saja akan menghasilkan error jika tipe data yang digunakan jauh berbeda.
#include <iostream>
using namespace std;
int main(){
    char c = 'A';
    cout << "Tanpa static_cast => "<< c << endl;
    cout << "Dengan static_cast => " << static_cast<int>(c) << endl;
}
Output :
Tanpa static_cast => A
Dengan static_cast => 65
Pada contoh di atas, static_cast digunakan untuk mengubah tipe data variabel yang ditampilkan dengan menggunakan cout. Type casting dengan static_cast diperlukan pada contoh di atas karena cout menampilkan isi variabel sesuai tipe data variabelnya.

Reinterpret_cast

Reinterpret_cast dapat digunakan untuk mengubah pointer dalam bahasa C++ menjadi pointer dengan tipe data yang berbeda. Biasanya, ini digunakan untuk memecah suatu nilai menjadi beberapa byte penyusunnya. Untuk lebih mudahnya, angkanya sebaiknya kalian tampilkan sebagai hexadesimal dengan printf.
#include <stdio.h> 
int main(){
unsigned short *s=new unsigned short(0xFFFE);
unsigned char *c=reinterpret_cast<unsigned char*>(s);
    printf("%#06X\n", *s);//tampilkan sebagai nilai hexa desimal
    printf("Byte Rendah : %#04X\n", c[0]);
    printf("Byte Tinggi : %#04X\n", c[1]);
    return 0;
}
Output :
0XFFFE
Byte Rendah : 0XFE
Byte Tinggi : 0XFF

Contoh di atas memecah variabel bertipe short yang ukurannya 2 byte menjadi pointer bertipe char yang ukurannya 1 byte. Printf pada contoh tersebut digunakan untuk menampilkan nilai hexadesimal yang terdiri dari 6 digit. Kalau kalian ingin menggunakan angka desimal berbasis sepuluh, ganti "%#06X" dengan "%d". Angka "06" bisa kalian ganti dengan jumlah digit hexadesimal lain sesuai keinginan kalian.

Const_cast

Const_cast memiliki beberapa kegunaan yang terkait dengan konstanta. Salah satu kegunaan dari const_cast adalah untuk memaksakan penggunaan konstanta sebagai parameter fungsi. Penggunaan konstanta dengan cara di bawah ini mungkin akan menyebabkan error karena function tersebut tidak menerima parameter berupa konstanta.
#include <iostream>
using namespace std;

int fungsiku(int* p){
    return (*p + 10);
}

int main(void){
    const int konstanta = 10;
    cout << fungsiku(&konstanta);
    return 0;
}
Supaya kode program tidak menghasilkan error, kalian bisa menggunakan const pada deklarasi parameter function-nya. Kalian bisa juga menggunakan const_cast seperti contoh di bawah ini. 
#include <iostream>
using namespace std;

int fungsiku(int* p){
    return (*p + 10);
}

int main(void){
    const int konstanta = 10;
    cout << "fungsiku(const_cast<int *>(&konstanta)) => " << fungsiku(const_cast<int *>(&konstanta)) << endl;
    return 0;
}
Output :
fungsiku(const_cast(&konstanta)) => 20

Dynamic_cast

Selain semua type casting di atas, ada juga dynamic_cast yang lebih sering digunakan untuk object. Dynamic cast bisa digunakan untuk mengubah class asal menjadi class turunannya sebelum disimpan ke pointer. Proses tersebut disebut dengan downcasting. Kebalikan dari downcasting adalah upcasting.

#include <iostream>

using namespace std;

class Anak{
     public:
         string adik;
         string kakak;
         Anak(string s1, string s2){
         	adik=s1;
         	kakak=s2;
         }
         void tampilkan_data(){
             cout << "Nama kakak : ";
             cout << kakak << endl;
             cout << "Nama adik : ";
             cout << adik << endl;
         }
};

class Keluarga : public Anak{
    public:
        string ayah;
        string ibu;
        
        Keluarga(string s1, string s2, string s3, string s4):Anak(s1, s2){
            ayah=s1;
            ibu=s2;
            adik=s3;
            kakak=s4;
        }
        
        void tampilkan_data(){
       	 cout << "Nama ayah!";
       	 cout << ayah << endl;
         cout << "Nama ibu : ";
       	 cout << ibu << endl;
         cout << "Nama kakak : ";
         cout << kakak << endl;
         cout << "Nama adik : ";
       	 cout << adik << endl;
        }
};

using namespace std;

int main(){
    Keluarga *var_base=new Keluarga("Toni", "Tono", "Tina", "Tino");
    Anak *var_cast=dynamic_cast<Anak*> (var_base);
    var_cast->tampilkan_data();
    return 0;
}
Output :
Nama kakak : Tino
Nama adik : Tina
Contoh di atas menggunakan method tampilkan_data dari class Anak walaupun inisiasi objeknya menggunakan constructor class Keluarga. Itu bisa dilakukan karena adanya dynamic_cast.

Keyword Virtual

Jika kalian ingin menggunakan method tampilkan pada class Keluarga, gunakan keyword virtual pada class Anak yang merupakan base class.
#include <iostream>

using namespace std;

class Anak{
     public:
         string adik;
         string kakak;
         Anak(string s1, string s2){
         	adik=s1;
         	kakak=s2;
         }
         virtual void tampilkan_data(){
             cout << "Nama kakak : ";
             cout << kakak << endl;
             cout << "Nama adik : ";
             cout << adik << endl;
         }
};

class Keluarga : public Anak{
    public:
        string ayah;
        string ibu;
        
        Keluarga(string s1, string s2, string s3, string s4):Anak(s1, s2){
            ayah=s1;
            ibu=s2;
            adik=s3;
            kakak=s4;
        }
        
        void tampilkan_data(){
       	 cout << "Nama ayah : ";
       	 cout << ayah << endl;
         cout << "Nama ibu : ";
       	 cout << ibu << endl;
         cout << "Nama kakak : ";
         cout << kakak << endl;
         cout << "Nama adik : ";
       	 cout << adik << endl;
        }
};

using namespace std;

int main(){
    Keluarga *var_base=new Keluarga("Toni", "Tono", "Tina", "Tino");
    Anak *var_cast=dynamic_cast<Anak*> (var_base);
    var_cast->tampilkan_data();
    return 0;
}
Output :
Nama ayah : Toni
Nama ibu : Tono
Nama kakak : Tino
Nama adik : Tina

Kalian bisa mencoba untuk menambahkan var_base->tampilkan_data() tanpa keyword virtual. Coba bandingkan hasilnya dengan var_cast->tampilkan_data.