#include <iostream>
#include <string>
// Forward declaration lets DisplayDriver know SPIBus exists
class SPIBus;
class DisplayDriver {
public:
// Defined later, once SPIBus is fully defined
void fastWrite(SPIBus& bus, int v1, int v2);
};
class SPIBus {
private:
int buffer[2];
// This line gives DisplayDriver full access to all private members of SPIBus
friend class DisplayDriver;
public:
SPIBus() {
buffer[0] = 0;
buffer[1] = 0;
}
void dump() {
std::cout << "Buffer: [ " << buffer[0] << " " << buffer[1] << " ]" << std::endl;
}
};
// Now that SPIBus is defined, we can implement the method that uses its internals
void DisplayDriver::fastWrite(SPIBus& bus, int v1, int v2) {
bus.buffer[0] = v1;
bus.buffer[1] = v2;
}
int main() {
SPIBus bus;
DisplayDriver driver;
int N;
if (!(std::cin >> N)) return 0;
for (int i = 0; i < N; ++i) {
std::string cmd;
std::cin >> cmd;
if (cmd == "WRITE") {
int v1, v2;
std::cin >> v1 >> v2;
driver.fastWrite(bus, v1, v2);
} else if (cmd == "SHOW") {
bus.dump();
}
}
return 0;
}Explanation & Logic Summary:
friend class DisplayDriver; inside SPIBus, we tell the compiler that DisplayDriver is "trusted."bus.buffer is invisible to the outside world. However, methods inside DisplayDriver can see and modify it just as if they were members of SPIBus.class SPIBus; at the top so DisplayDriver could mention it in a function signature (fastWrite) before SPIBus was fully defined. We defined the body of fastWrite at the bottom, after SPIBus was fully defined, so it knew buffer existed.Firmware Relevance & Real-World Context:
friend allows this specific bypass without making the HAL public to everyone.TestRunner class can be a friend of the MotorController to inject fake error states or sensor readings into private variables that are otherwise read-only (hardware inputs).
Input
3 SHOW WRITE 55 99 SHOW
Expected Output
Buffer: [ 0 0 ] Buffer: [ 55 99 ]