Menu
CoddyTech

Polimorfisme saat Compile vs Runtime

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 56 dari 104.

Polymorphism berarti "banyak bentuk" dan merupakan konsep inti OOP yang memungkinkan object diperlakukan secara seragam sambil berperilaku berbeda. C++ mendukung dua jenis polymorphism yang berbeda, masing-masing diselesaikan pada tahap yang berbeda dalam eksekusi program.

Polimorfisme waktu kompilasi (juga disebut polimorfisme statis) ditentukan oleh kompiler sebelum program dijalankan. Kompiler menentukan dengan tepat fungsi mana yang akan dipanggil berdasarkan signature fungsi. Ini mencakup overloading fungsi dan template:

void print(int x) { std::cout << "Integer: " << x << std::endl; }
void print(double x) { std::cout << "Double: " << x << std::endl; }

print(5);      // Compiler memilih print(int)
print(3.14);   // Compiler memilih print(double)

Polimorfisme saat runtime (juga disebut polimorfisme dinamis) ditentukan saat program berjalan. Keputusan tentang fungsi mana yang akan dipanggil bergantung pada tipe object sebenarnya, bukan tipe pointer atau reference. Hal ini dicapai melalui fungsi virtual:

class Shape {
public:
    virtual void draw() { std::cout << "Drawing shape" << std::endl; }
};

class Circle : public Shape {
public:
    void draw() override { std::cout << "Drawing circle" << std::endl; }
};

Shape* s = new Circle();
s->draw();  // Ditentukan saat program berjalan: "Drawing circle"

Kompromi utamanya: polimorfisme saat kompilasi tidak memiliki overhead runtime karena keputusan dibuat selama kompilasi, sedangkan polimorfisme runtime menambah sedikit biaya (pencarian vtable), tetapi memberikan fleksibilitas lebih besar saat bekerja dengan object yang tipenya belum diketahui sampai program dijalankan.

challenge icon

Tantangan

Mudah

Mari buat sistem kalkulator yang menunjukkan kedua jenis polimorfisme secara berdampingan. Kamu akan membuat sistem yang menggunakan polimorfisme waktu kompilasi untuk menangani berbagai tipe input melalui overloading fungsi, sementara polimorfisme waktu runtime memungkinkan strategi perhitungan yang berbeda ditukar secara dinamis.

Kamu akan mengatur kodemu dalam tiga file:

  • Calculator.h: Definisikan base Calculator class yang mewakili strategi perhitungan apa pun:
    • Method virtual calculate(int a, int b) yang mengembalikan int dan mencetak: Base calculation: <a> ? <b> (mengembalikan 0)
    • Destructor virtual
  • Operations.h: Definisikan dua class kalkulator turunan yang menimpa perilaku perhitungan:
    • Adder: Timpa calculate() agar mencetak Adding: <a> + <b> dan mengembalikan jumlahnya
    • Multiplier: Timpa calculate() agar mencetak Multiplying: <a> * <b> dan mengembalikan hasil kalinya
    Kedua class harus menggunakan kata kunci override.
  • main.cpp: Buat sistem yang menunjukkan kedua jenis polimorfisme. Baca dua input bilangan bulat (masing-masing pada baris terpisah).

    Pertama, tunjukkan polimorfisme waktu kompilasi dengan membuat tiga fungsi display() yang di-overload:

    • display(int x) mencetak: Integer value: <x>
    • display(double x) mencetak: Double value: <x>
    • display(const std::string& x) mencetak: String value: <x>

    Lalu, tunjukkan polimorfisme waktu runtime dengan membuat array berisi pointer Calculator* yang menunjuk ke sebuah Calculator dasar, sebuah Adder, dan sebuah Multiplier. Lakukan perulangan dan panggil calculate() pada masing-masing dengan nilai inputmu, lalu cetak hasilnya setelah setiap perhitungan.

    Susun outputmu seperti berikut:

    === Compile-Time Polymorphism ===
    <display outputs for int, double, string>
    
    === Runtime Polymorphism ===
    <calculate outputs with results>

    Untuk bagian waktu kompilasi, panggil display() dengan input pertama sebagai bilangan bulat, lalu sebagai bilangan double (nilai yang sama ditambah .5), kemudian sebagai string "Result". Bersihkan kalkulator yang dialokasikan secara dinamis setelah selesai.

Contohnya, dengan input 10 dan 3:

=== Compile-Time Polymorphism ===
Integer value: 10
Double value: 10.5
String value: Result

=== Runtime Polymorphism ===
Base calculation: 10 ? 3
Result: 0
Adding: 10 + 3
Result: 13
Multiplying: 10 * 3
Result: 30

Perhatikan bagaimana compiler memilih overload display() yang tepat berdasarkan tipe argumen (keputusan waktu kompilasi), sementara method calculate() yang tepat ditentukan oleh tipe object sebenarnya saat runtime melalui mekanisme vtable.

Coba sendiri

#include <iostream>
#include <string>
#include "Calculator.h"
#include "Operations.h"

// TODO: Buat tiga fungsi display() yang di-overload:
// 1. display(int x): mencetak "Integer value: <x>"
// 2. display(double x): mencetak "Double value: <x>"
// 3. display(const std::string& x): mencetak "String value: <x>"



int main() {
    // Baca dua input bilangan bulat
    int a, b;
    std::cin >> a;
    std::cin >> b;
    
    // === Compile-Time Polymorphism ===
    std::cout << "=== Compile-Time Polymorphism ===" << std::endl;
    // TODO: Panggil display() dengan:
    // - a sebagai bilangan bulat
    // - a sebagai double (tambahkan 0.5 ke a)
    // - string "Result"
    
    
    std::cout << std::endl;
    
    // === Runtime Polymorphism ===
    std::cout << "=== Runtime Polymorphism ===" << std::endl;
    // TODO: Buat array berisi pointer Calculator* dengan 3 elemen:
    // - Calculator dasar
    // - Adder
    // - sebuah Multiplier
    
    // TODO: Telusuri array dengan perulangan, lalu panggil calculate(a, b) pada setiap elemennya,
    // dan cetak "Result: <return_value>" setelah setiap perhitungan
    
    
    // TODO: Bebaskan memori yang dialokasikan secara dinamis
    
    
    return 0;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online