❥关于C++之友元类
Posted itzyjr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❥关于C++之友元类相关的知识,希望对你有一定的参考价值。
友元类的所有方法都可以访问原始类的私有成员和保护成员。
看一个电视与遥控器的示例。遥控器可以改变电视机的状态,这表明应将Romote类作为Tv类的一个友元。
// tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_
class Tv
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
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
;
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
// tv.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv.h"
bool Tv::volup()
if (volume < MaxVal)
volume++;
return true;
return false;
bool Tv::voldown()
if (volume > MinVal)
volume--;
return true;
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;
//use_tv.cpp -- using the Tv and Remote classes
#include <iostream>
#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;
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
关键点:友元类的所有方法都可以访问原始类的私有成员和保护成员。只需在原始类中加上一句声明:friend class Remote; 即让Remote类成为原始类的友元类。
如果想让只有特定的Remote方法是Tv类的友元呢?
假设只让Remote类的set_chan方法成为Tv类的友元,只需将友元类声明那行替换为:
class Tv
public:
friend void Remote::set_chan(Tv& t, int c);// 替换friend class Remote;
...
区别在于,只有一个Remote方法(称之为友元成员函数)是Tv类的友元,而在原来的版本中,所有的Remote方法都是Tv类的友元。
对于友元成员函数,存在个问题,如下:(对于友元类不存在这个问题)
前向声明与正确的排列顺序:
要使编译器能够处理这条语句,它必须知道Remote的定义。否则,它无法知道Remote是一个类,而set_chan是这个类的方法。这意味着应将Remote的定义放到Tv的定义前面。Remote的方法提到了Tv对象,而这意味着Tv定义应当位于Remote定义之前。避开这种循环依赖的方法是,使用前向声明(forward declaration)。为此,需要在Remote定义的前面插入下面的语句:
class Tv;// forward declaration
正确的排列:
class Tv; ←前向声明
class Remote void set_chan(Tv & t, int c) t.channel = c;...;
class Tv friend void Remote::set_chan(Tv& t, int c);...;
————————————————————————
不能像下面这样排列:
class Remote; ←前向声明
class Tv friend void Remote::set_chan(Tv& t, int c);...;
class Remote void set_chan(Tv & t, int c) t.channel = c;...;
不能用以上的第二种排列方式,原因在于:在编译器在Tv类的声明中看到Remote的一个方法被声明为Tv类的友元之前,应该先看到Remote类的声明和set_chan方法的声明。
对于友元成员函数参数中用到原始类类型的情况,正确的排列顺序就是:
原始类的前向声明->友元类定义->原始类定义
共同的友元函数:
所谓“共同”就是:友元函数是一个类的成员,同时也是另一个类的成员。
例如,假定有一个Probe类和一个Analyzer类,前者表示某种可编程的测量设备,后者表示某种可编程的分析设备。这两个类都有内部时钟,且希望它们能够同步,则应该包含下述代码行:
class Analyzer; ←前向声明
class Probe
friend void sync(Analyzer& a, const Probe& p);// sync a to p
friend void sync(Probe& p, const Analyzer& a);// sync p to a
...
;
class Analyzer
friend void sync(Analyzer& a, const Probe& p);// sync a to p
friend void sync(Probe& p, const Analyzer& a);// sync p to a
...
;
// define the friend functions
inline void sync(Analyzer& a, const Probe& p) ...
inline void sync(Probe& p, const Analyzer& a) ...
前向声明使编译器看到Probe类声明中的友元声明时,知道Analyzer是一种类型。
以上是关于❥关于C++之友元类的主要内容,如果未能解决你的问题,请参考以下文章