Menu
CoddyTech

Fungsi Virtual Murni

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

Fungsi virtual murni adalah fungsi virtual yang tidak memiliki implementasi di class dasar. Fungsi ini dideklarasikan dengan menetapkan = 0 pada deklarasi fungsi. Ini memberi tahu kompiler bahwa class turunan wajib menyediakan implementasinya sendiri.

class Shape {
public:
    virtual double area() = 0;  // Fungsi virtual murni
    virtual ~Shape() = default;
};

Berbeda dengan fungsi virtual biasa yang menyediakan perilaku default, fungsi virtual murni menetapkan kontrak: setiap class turunan konkret harus mengimplementasikan fungsi ini agar dapat dibuat instance-nya. Class dasar hanya menyatakan apa yang harus dilakukan, bukan bagaimana.

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() override {
        return 3.14159 * radius * radius;
    }
};

class Rectangle : public Shape {
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    
    double area() override {
        return width * height;
    }
};

Circle dan Rectangle harus mengimplementasikan area() karena fungsi tersebut bersifat virtual murni di Shape. Jika class turunan gagal mengimplementasikan semua fungsi virtual murni, class tersebut juga menjadi abstrak dan tidak dapat dibuat sebagai instance.

Fungsi virtual murni penting ketika base class tidak dapat menyediakan implementasi default yang bermakna. Setiap bentuk memiliki luas, tetapi tidak ada cara yang masuk akal untuk menghitung "luas bentuk umum" tanpa mengetahui tipe bentuk yang spesifik.

challenge icon

Tantangan

Mudah

Mari kita bangun sistem pemrosesan pembayaran yang menunjukkan cara fungsi virtual murni menegakkan kontrak untuk berbagai metode pembayaran. Kamu akan membuat class dasar abstrak yang menentukan hal yang harus dilakukan setiap pemroses pembayaran, lalu menerapkan tipe pembayaran konkret yang memenuhi kontrak tersebut.

Kamu akan mengatur kodemu dalam tiga file:

  • PaymentProcessor.h: Definisikan class abstrak PaymentProcessor yang menjadi cetak biru untuk semua metode pembayaran. Class ini harus memiliki:
    • Member std::string accountId yang dilindungi
    • Konstruktor yang menginisialisasi ID akun
    • Method virtual murni processPayment(double amount): setiap tipe pembayaran harus menerapkannya dengan cara yang berbeda
    • Method virtual murni getProcessorName() yang mengembalikan std::string
    • Destruktor virtual
  • PaymentMethods.h: Terapkan dua pemroses pembayaran konkret yang mewarisi PaymentProcessor:

    CreditCardProcessor:

    • Member double feePercentage privat (tarif biaya transaksi)
    • Konstruktor yang menerima ID akun dan persentase biaya
    • Terapkan processPayment() untuk menghitung biaya (amount * feePercentage / 100), lalu mencetak:
      Credit Card [<accountId>]: Charged $<amount> (Fee: $<fee>)
    • Terapkan getProcessorName() untuk mengembalikan "CreditCard"

    BankTransferProcessor:

    • Member std::string bankName privat
    • Konstruktor yang menerima ID akun dan nama bank
    • Terapkan processPayment() untuk mencetak:
      Bank Transfer [<accountId>] via <bankName>: Transferred $<amount>
    • Terapkan getProcessorName() untuk mengembalikan "BankTransfer"
  • main.cpp: Baca empat input (masing-masing pada baris terpisah):
    1. ID akun kartu kredit
    2. Persentase biaya kartu kredit (double)
    3. ID akun bank
    4. Nama bank

    Buat kedua pemroses pembayaran dan simpan dalam array berisi pointer PaymentProcessor*. Proses pembayaran sebesar 100.0 melalui setiap pemroses, dengan menampilkan nama pemroses sebelum setiap transaksi:

    Processing with <processorName>:
    <processPayment output>

    Cetak satu baris kosong di antara pemroses. Hapus object yang dialokasikan secara dinamis setelah selesai.

Contohnya, dengan input CC-4521, 2.5, BA-7890, dan National Bank:

Processing with CreditCard:
Credit Card [CC-4521]: Charged $100 (Fee: $2.5)

Processing with BankTransfer:
Bank Transfer [BA-7890] via National Bank: Transferred $100

Karena PaymentProcessor memiliki fungsi virtual murni, kamu tidak dapat membuat instance-nya secara langsung: hanya implementasi konkret yang memenuhi kontrak yang dapat dibuat. Ini memastikan setiap metode pembayaran menyediakan logika pemrosesan spesifiknya sendiri.

Coba sendiri

#include <iostream>
#include <string>
#include "PaymentMethods.h"

using namespace std;

int main() {
    // Baca input
    string ccAccountId;
    double feePercentage;
    string bankAccountId;
    string bankName;
    
    getline(cin, ccAccountId);
    cin >> feePercentage;
    cin.ignore();
    getline(cin, bankAccountId);
    getline(cin, bankName);
    
    // TODO: Buat array berisi 2 pointer PaymentProcessor*
    
    // TODO: Buat object CreditCardProcessor dan BankTransferProcessor
    // dan simpan keduanya dalam array
    
    // TODO: Lakukan perulangan pada array dan untuk setiap processor:
    // 1. Cetak "Processing with <processorName>:"
    // 2. Panggil processPayment dengan jumlah 100.0
    // 3. Cetak baris kosong di antara processor (bukan setelah yang terakhir)
    
    // TODO: Hapus object 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