void onoff() {state = (state == On)? Off : On;}
bool ison() const {return state == On;}
bool volup();
bool voldown();
void chanup();
void chandown();
void set_mode() {mode = (mode == Antenna)? Cable : Antenna;}
void set_input() {input = (input == TV)? DVD : TV;}
void settings() const; // display all settings
private:
int state; // on or off
int volume; // assumed to be digitized
int maxchannel; // maximum number of channels
int channel; // current channel setting
int mode; // broadcast or cable
int input; // TV or DVD
};
class Remote
{
private:
int mode; // controls TV or DVD
public:
Remote(int m = Tv::TV) : mode(m) {}
bool volup(Tv & t) { return t.volup();}
bool voldown(Tv & t) { return t.voldown();}
void onoff(Tv & t) { t.onoff(); }
void chanup(Tv & t) {t.chanup();}
void chandown(Tv & t) {t.chandown();}
void set_chan(Tv & t, int c) {t.channel = c;}
void set_mode(Tv & t) {t.set_mode();}
void set_input(Tv & t) {t.set_input();}
};
#endif
Most of the class methods in Listing 15.1 are defined inline. Note that each Remote method other than the constructor takes a reference to a Tv object as an argument. This reflects that a remote has to be aimed at a particular TV. Listing 15.2 shows the remaining definitions. The volume-setting functions change the volume member by one unit unless the sound has reached its minimum or maximum setting. The channel selection functions use wraparound, with the lowest channel setting, taken to be 1, immediately following the highest channel setting, maxchannel.
Many of the methods use the conditional operator to toggle a state between two settings:
void onoff() {state = (state == On)? Off : On;}
Provided that the two state values are true and false, or, equivalently, 0 and 1, this can be done more compactly by using the combined bitwise exclusive OR and assignment operator (^=), as discussed in Appendix E, “Other Operators”:
void onoff() {state ^= 1;}
In fact, you could store up to eight bivalent state settings in a single unsigned char variable and toggle them individually, but that’s another story, one made possible by the bitwise operators discussed in Appendix E.
Listing 15.2. tv.cpp
// tv.cpp -- methods for the Tv class (Remote methods are inline)
#include
#include "tv.h"
bool Tv::volup()
{
if (volume < MaxVal)
{
volume++;
return true;
}
else
return false;
}
bool Tv::voldown()
{
if (volume > MinVal)
{
volume--;
return true;
}
else
return false;
}
void Tv::chanup()
{
if (channel < maxchannel)
channel++;
else
channel = 1;
}
void Tv::chandown()
{
if (channel > 1)
channel--;
else
channel = maxchannel;
}
void Tv::settings() const
{
using std::cout;
using std::endl;
cout << "TV is " << (state == Off? "Off" : "On") << endl;
if (state == On)
{
cout << "Volume setting = " << volume << endl;
cout << "Channel setting = " << channel << endl;
cout << "Mode = "
<< (mode == Antenna? "antenna" : "cable") << endl;
cout << "Input = "
<< (input == TV? "TV" : "DVD") << endl;
}
}
Listing 15.3 is a short program that tests some of the features of the program so far. The same controller is used to control two separate televisions.
Listing 15.3. use_tv.cpp
//use_tv.cpp -- using the Tv and Remote classes
#include
#include "tv.h"
int main()
{
using std::cout;
Tv s42;
cout << "Initial settings for 42\" TV:\n";
s42.settings();
s42.onoff();
s42.chanup();
cout << "\nAdjusted settings for 42\" TV:\n";
s42.settings();
Remote grey;
grey.set_chan(s42, 10);
grey.volup(s42);
grey.volup(s42);
cout << "\n42\" settings after using remote:\n";
s42.settings();
Tv s58(Tv::On);
s58.set_mode();
grey.set_chan(s58,28);
cout << "\n58\" settings:\n";
s58.settings();
return 0;
}
Here is the output of the program in Listings 15.1, 15.2, and 15.3:
Initial settings for 42" TV:
TV is Off
Adjusted settings for 42" TV:
TV is On
Volume setting = 5
Channel setting = 3
Mode = cable
Input = TV
42" settings after using remote:
TV is On
Volume setting = 7
Channel setting = 10
Mode = cable
Input = TV
58" settings:
TV is On
Volume setting = 5
Channel setting = 28
Mode = antenna
Input = TV
The main point to this exercise is that class friendship is a natural idiom in which to express some relationships. Without some form of friendship, you would either have to make the private parts of the Tv class public or else construct some awkward, larger class that encompasses both a television and a remote control. And that solution wouldn’t reflect the fact that a single remote control can be used with several televisions.
Friend Member Functions