Observer pattern
You could use an Observer pattern, which provides a general way for the Engine to pass a notification to an arbitrary interested party (often you'd allow multiple observers who'd all be notified, but for this purpose supporting one is enough).
struct IEngineObserver
{
virtual void on_overheated() = 0;
};
class Engine
{
public:
Engine(IEngineObserver& observer) : observer_(observer) { }
void start()
{
temperature_ = 15;
}
void rev()
{
if ((temperature_ += 2) > 50)
on_overheated();
}
IEngineObserver& observer_;
int temperature_;
};
class Radio
{
public:
void open() {}
};
class Car : public IEngineObserver
{
public:
Car() : engine_(this), finito_(false) { }
~Car();
virtual void on_overheat() override { finito_ = true; }
Engine engine_;
Radio radio_;
bool finito_;
};
You can then loop until car.finito_
is true
. It doesn't make sense to delete
the Car from within the Engine though, if you have some code in main()
continually invoking operations on the Car object... that will crash. The Car
will be destroyed when it goes out of scope at the end of main
, so your focus should be on breaking out of the rev()
ing loop at the right time - i.e. when finito_
is set.
Lambda and std::function
Something similar can be done with lambdas and std::function
, so that the Car can specify arbitrary code for the engine to run when it overheats as in...
Car() : engine_([&] () { finito_ = true; }), finito_(false) { }
Engine(std::function<void (*)()>& f) : f_(f) { }
...without needing an extra IEngineObserver
class or on_overheat
functions.