#include <iostream>
using namespace std;
class ClockController {
public:
ClockController() {
cout << "Clock enabled" << endl;
}
~ClockController() {
cout << "Clock disabled" << endl;
}
void write(int offset, int value) {
cout << "Clocked write: " << offset << " " << value << endl;
}
};
class Peripheral {
private:
ClockController& clk;
public:
Peripheral(ClockController& c) : clk(c) {
cout << "Peripheral ready" << endl;
}
~Peripheral() {
cout << "Peripheral stopped" << endl;
}
void writeReg(int offset, int value) {
clk.write(offset, value);
}
};
class Driver {
private:
ClockController clk;
Peripheral periph;
public:
Driver() : periph(clk) {
cout << "Driver started" << endl;
}
void operate(int offset, int value) {
periph.writeReg(offset, value);
}
~Driver() {
cout << "Driver stopped" << endl;
}
};
int main() {
int offset, value;
cin >> offset >> value;
{
Driver drv;
drv.operate(offset, value);
}
return 0;
}
Explanation & Logic Summary:
This problem demonstrates dependency-aware composition, where one component cannot function unless another component is already active.
The Driver owns the ClockController, making it responsible for enabling and disabling the clock.
The Peripheral does not own the clock; instead, it depends on an existing clock instance via a reference.
Because references:
the following guarantees are enforced:
Constructor order guarantees safe startup:
Destructor order guarantees safe shutdown:
Firmware Relevance & Real-World Context:
On real microcontrollers, peripherals such as UART, SPI, I2C, timers, and ADCs require their clocks to be enabled before any register access.
Violating this rule can cause:
By encoding hardware dependencies directly into C++ class relationships:
This makes dependency-aware composition a core embedded C++ design skill.
Input
8 55
Expected Output
Clock enabled Peripheral ready Driver started Clocked write: 8 55 Driver stopped Peripheral stopped Clock disabled