几点说明:
- 使用friend class Remote; 就起到了Remote的前向声明的作用,不用在Tv声明前单加class Remote;
- 仅有friend class Remote; 编译器仅知道Remote是一个类名,但类内的成员(数据成员或函数)如果出现,编译器仍然不知道如何处理
- 结合第2条,Tv中出现的访问Remote私有成员的Tv的成员函数,必须在Remote类定义完成后再单独添加定义
- 在类外进行定义时,未debug状态下即标红报错:与类声明不兼容。但仍能运行,这点没搞懂,后续跟进吧。
tv.h
// tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_
class Tv
{
public:
friend class Remote; // Remote can access Tv private parts
enum { Off, On };
enum { MinVal, MaxVal = 20 };
enum { Antenna, Cable };
enum { TV, DVD };
Tv(int s = Off, int mc = 125) : state(s), volume(5),
maxchannel(mc), channel(2), mode(Cable), input(TV) {}
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
// newly added
// approach 1: Tv is Remote's friend class,can visit Remote's private members
bool set_modeIA(Remote& r);
// approach 2: as an outside program,still can visit Remote's public class
// bool set_modeIA(Remote& r);
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:
friend class Tv;
int mode; // controls TV or DVD
// newly added mode member
enum { normal, interactive };
int modeIA;
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(); }
// newly added
bool isnormal() { return modeIA == normal; }
// remote must has the function to change its mode by itself
// operating own members,no need to use Tv& as parameter
void set_modeIA() { modeIA = (modeIA == normal) ? interactive : normal;}
};
// implementations for approach 1
inline bool Tv::set_modeIA(Remote& r)
{
if (ison())
{
r.modeIA = (r.modeIA == r.normal) ? r.interactive : r.normal;
return true;
}
else
return false;
}
/*
// implementations for approach 2
bool Tv::set_modeIA(Remote& r)
{
if (ison())
{
r.set_modeIA();
return true;
}
else
return false;
}
*/
#endif
main.cpp
#include<iostream>
#include"tv.h"
using std::cout;
using std::endl;
using std::cin;
void show(Tv&t, Remote&r);// protetype
int main()
{
cout << "By default, tv is off" << endl;
Tv t1;
Remote r1;
show(t1, r1);
cout << "\nNow use Tv set remote's modeIA" << endl;
t1.set_modeIA(r1);
show(t1, r1);
cout << "\nNow turn on the TV, try to use Tv set remote's modeIA" << endl;
r1.onoff(t1);
t1.set_modeIA(r1);
show(t1, r1);
cin.get();
}
void show(Tv&t,Remote&r)
{
if (t.ison())
cout << "Tv state is on" << endl;
else
cout << "Tv state is off" << endl;
if (r.isnormal())
cout << "Remote state is normal" << endl;
else
cout << "Remote state is interactive" << endl;
}