128. Abstract Communication Driver

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

class CommDriver {
public:
    virtual void send(const string& data) = 0;
    virtual string receive() = 0;
    virtual ~CommDriver() = default;
};

class UartDriver : public CommDriver {
private:
    string last;
public:
    void send(const string& data) override {
        last = data;
        cout << "UART SEND: " << data << "\n";
    }

    string receive() override {
        return string("UART RECV: ") + last;
    }
};

class SpiDriver : public CommDriver {
private:
    string last;
public:
    void send(const string& data) override {
        last = data;
        cout << "SPI SEND: " << data << "\n";
    }

    string receive() override {
        return string("SPI RECV: ") + last;
    }
};

int main() {
    string type, msg;
    cin >> type >> msg;

    CommDriver* driver = nullptr;

    if (type == "UART") {
        driver = new UartDriver();
    } else if (type == "SPI") {
        driver = new SpiDriver();
    }

    if (driver) {
        driver->send(msg);
        cout << driver->receive();
        delete driver;
    }

    return 0;
}

Explanation & Logic Summary
The base class CommDriver declares send() and receive() as pure virtual functions, making it an abstract class. This prevents direct instantiation and enforces a contract that all communication drivers must follow.

UartDriver and SpiDriver implement this interface. By using a CommDriver* pointer, the program achieves runtime polymorphism, allowing the same code to work with different communication backends.

Firmware Relevance & Real-World Context
This pattern mirrors real embedded firmware design, where UART, SPI, or I2C drivers expose a common interface. Higher-level modules interact with peripherals through this abstraction, improving portability, modularity, and long-term maintainability across hardware platforms.

 

 


 

Loading...

Input

UART Hello

Expected Output

UART SEND: Hello UART RECV: Hello