What Are the Objects? One way to approach this problem is to set aside issues relating to the user interface and to focus only on the comp...
What Are the Objects?
One way to approach this problem is to set aside issues relating to the user interface and to focus only on the components of the "problem space." A first approximation of an object-oriented design might be to list the objects that you need to simulate, and then to examine what these objects "know" and "do."
New Term: The problem space is the set of problems and issues your program is trying to solve. The solution space is the set of possible solutions to the problems.
For example, clearly you have sensors of various types, a central alarm system, buttons, wires, and telephones. Further thought convinces you that you must also simulate rooms, perhaps floors, and possibly groups of people such as owners and police.
The sensors can be divided into motion detectors, trip wires, sound detectors, smoke detectors, and so forth. All of these are types of sensors, though there is no such thing as a sensor per se. This is a good indication that sensor is an abstract data type (ADT).
As an ADT, the class sensor would provide the complete interface for all types of sensors, and each derived type would provide the implementation. Clients of the various sensors would use them without regard to which type of sensor they are, and they would each "do the right thing" based on their real type.
To create a good ADT, you need to have a complete understanding of what sensors do (rather than how they work). For example, are sensors passive devices or are they active? Do they wait for some element to heat up, a wire to break, or a piece of caulk to melt, or do they probe their environment? Perhaps some sensors have only a binary state (alarm state or okay), but others have a more analog state (what is the current temperature?). The interface to the abstract data type should be sufficiently complete to handle all the anticipated needs of the myriad derived classes.
Other Objects
The design continues in this way, teasing out the various other classes that will be required to meet the specification. For example, if a log is to be kept, probably a timer will be needed; should the timer poll each sensor or should each sensor file its own report periodically?
The user is going to need to be able to set up, disarm, and program the system, and so a terminal of some sort will be required. You may want a separate object in your simulation for the alarm program itself.
What Are the Classes?
As you solve these problems, you will begin to design your classes. For example, you already have an indication that HeatSensor will derive from Sensor. If the sensor is to make periodic reports, it may also derive via multiple inheritance from Timer, or it may have a timer as a member variable.
The HeatSensor will probably have member functions such as CurrentTemp() and SetTempLimit() and will probably inherit functions such as SoundAlarm() from its base class, Sensor.
A frequent issue in object-oriented design is that of encapsulation. You could imagine a design in which the alarm system has a setting for MaxTemp. The alarm system asks the heat sensor what the current temperature is, compares it to the maximum temperature, and sounds the alarm if it is too hot. One could argue that this violates the principle of encapsulation. Perhaps it would be better if the alarm system didn't know or care what the details are of temperature analysis; arguably that should be in the HeatSensor.
Whether or not you agree with that argument, it is the kind of decision you want to focus on during the analysis of the problem. To continue this analysis, one could argue that only the Sensor and the Log object should know any details of how sensor activity is logged; the Alarm object shouldn't know or care.
Good encapsulation is marked by each class having a coherent and complete set of responsibilities, and no other class having the same responsibilities. If the sensor is responsible for noting the current temperature, no other class should have that responsibility.
On the other hand, other classes might help deliver the necessary functionality. For example, while it might be the responsibility of the Sensor class to note and log the current temperature, it might implement that responsibility by delegating to a Log object the job of actually recording the data.
Maintaining a firm division of responsibilities makes your program easier to extend and maintain. When you decide to change the alarm system for an enhanced module, its interface to the log and to the sensors will be narrow and well defined. Changes to the alarm system should not affect the Sensor classes, and vice versa.
Should the HeatSensor have a ReportAlarm() function? All sensors will need the ability to report an alarm. This is a good indication that ReportAlarm() should be a virtual method of Sensor, and that Sensor may be an abstract base class. It is possible that HeatSensor will chain up to Sensor's more general ReportAlarm() method; the overridden function would just fill in the details it is uniquely qualified to supply.