Skillversitas

Abstract Classes and Interfaces in C++

An abstract class is a class that has at least one pure virtual function. A pure virtual function is declared with = 0 at the end of its declaration. An abstract class cannot have its objects created, but it can be used as a pointer or reference type to support polymorphism.

An interface in C++ is a class whose members are all pure virtual functions. An interface defines the contract that must be fulfilled by all classes that inherit from it.

Code Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class PaymentProcessor {
public:
    virtual bool processPayment(double amount) = 0;
    virtual bool refundPayment(double amount) = 0;
    virtual string getProcessorName() = 0;
    virtual ~PaymentProcessor() {}
};

class CreditCardProcessor : public PaymentProcessor {
private:
    string cardNumber;
    string cardHolder;

public:
    CreditCardProcessor(string card, string holder) : cardNumber(card), cardHolder(holder) {}

    bool processPayment(double amount) override {
        cout << "Processing credit card payment: $ " << amount << endl;
        cout << "Card: ****" << cardNumber.substr(cardNumber.length() - 4) << endl;
        return true;
    }

    bool refundPayment(double amount) override {
        cout << "Credit card refund: $ " << amount << endl;
        return true;
    }

    string getProcessorName() override {
        return "Credit Card";
    }
};

class BankTransferProcessor : public PaymentProcessor {
private:
    string bankName;
    string accountNumber;

public:
    BankTransferProcessor(string bank, string account) : bankName(bank), accountNumber(account) {}

    bool processPayment(double amount) override {
        cout << "Bank transfer from " << bankName << ": $ " << amount << endl;
        cout << "Account: " << accountNumber << endl;
        return true;
    }

    bool refundPayment(double amount) override {
        cout << "Bank transfer refund: $ " << amount << endl;
        return true;
    }

    string getProcessorName() override {
        return "Bank Transfer " + bankName;
    }
};

class EWalletProcessor : public PaymentProcessor {
private:
    string walletName;

public:
    EWalletProcessor(string name) : walletName(name) {}

    bool processPayment(double amount) override {
        cout << "Payment " << walletName << ": $ " << amount << endl;
        return true;
    }

    bool refundPayment(double amount) override {
        cout << "Refund " << walletName << ": $ " << amount << endl;
        return true;
    }

    string getProcessorName() override {
        return walletName;
    }
};

void checkout(PaymentProcessor* processor, double amount) {
    cout << "=== Checkout ===" << endl;
    cout << "Method: " << processor->getProcessorName() << endl;

    if (processor->processPayment(amount)) {
        cout << "Payment successful!" << endl;
    } else {
        cout << "Payment failed!" << endl;
    }
    cout << endl;
}

int main() {
    CreditCardProcessor cc("1234567890123456", "John Smith");
    BankTransferProcessor bt("ABC Bank", "1234567890");
    EWalletProcessor ew("PayGo");

    checkout(&cc, 500000);
    checkout(&bt, 250000);
    checkout(&ew, 100000);

    cout << "=== Refund ===" << endl;
    cc.refundPayment(100000);
    bt.refundPayment(50000);

    return 0;
}

Code Explanation

  1. virtual bool processPayment(double amount) = 0 - A pure virtual function. The = 0 marks that this function has no implementation in the base class and must be implemented in the derived class.

  2. class PaymentProcessor - An abstract class because it has pure virtual functions. You cannot create an object PaymentProcessor pp; but you can have PaymentProcessor* ptr;.

  3. class CreditCardProcessor : public PaymentProcessor - A concrete class that inherits from PaymentProcessor and implements all the pure virtual functions.

  4. virtual ~PaymentProcessor() {} - An empty virtual destructor in the abstract class. Important for proper cleanup through a base class pointer.

  5. void checkout(PaymentProcessor* processor, double amount) - A function that receives a pointer to an abstract class. It can receive a CreditCardProcessor, BankTransferProcessor, or EWalletProcessor object.

  6. processor->getProcessorName() - A dynamic virtual function call based on the actual object type passed to the function.

  7. All pure virtual functions must be implemented in the derived class for it to become a concrete class. Otherwise, the derived class is also abstract.

  8. A C++ interface is a class whose members are all pure virtual functions. It has no concrete data members.

Everyday Use Cases

Imagine an automatic ticket machine at a station. The machine defines an interface: select a destination, pay, print a ticket. Each payment vendor (credit card, e-wallet, bank transfer) must follow the same interface. You do not need to know the details of how each vendor works — just send instructions through the same interface.

Conclusion

An abstract class has at least one pure virtual function and cannot have its objects created. An interface is a class whose members are all pure virtual functions. Use an abstract class when there is basic shared behavior among derived classes. Use an interface when you only define a contract without any implementation. A virtual destructor must exist in an abstract class for proper cleanup.