#include <iostream>
using namespace std;
class Buffer {
private:
int data;
public:
Buffer() {
cout << "Buffer created" << endl;
}
~Buffer() {
cout << "Buffer destroyed" << endl;
}
void write(int value) {
data = value;
}
int read() const {
return data;
}
};
class RegisterBlock {
private:
int reg;
public:
RegisterBlock() {
cout << "RegisterBlock created" << endl;
}
~RegisterBlock() {
cout << "RegisterBlock destroyed" << endl;
}
void write(int value) {
reg = value;
}
int read() const {
return reg;
}
};
class Driver {
private:
Buffer buf; // Constructed first
RegisterBlock regs; // Constructed second
public:
Driver(int a, int b) {
buf.write(a);
regs.write(b);
cout << "Driver initialized" << endl;
}
void print() const {
cout << "Buffer value: " << buf.read() << endl;
cout << "Register value: " << regs.read() << endl;
}
~Driver() {
cout << "Driver destroyed" << endl;
}
};
int main() {
int a, b;
cin >> a >> b;
{
Driver drv(a, b);
drv.print();
}
return 0;
}
Explanation & Logic Summary:
The Driver class owns both Buffer and RegisterBlock as direct member objects.
Because C++ constructs class members in declaration order, the buffer is created first, followed by the register block.
When the driver goes out of scope, its destructor runs first, and then member objects are destroyed in reverse order.
This guarantees deterministic lifetime management without dynamic allocation.
Firmware Relevance & Real-World Context:
Real embedded drivers often manage multiple tightly coupled internal resources such as buffers, registers, and control blocks.
Using composition ensures clear ownership, prevents misuse from outside code, and guarantees predictable cleanup—essential for stable and safe firmware systems.
Input
10 20
Expected Output
Buffer created RegisterBlock created Driver initialized Buffer value: 10 Register value: 20 Driver destroyed RegisterBlock destroyed Buffer destroyed