加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 经验 > 正文

C++中友元的实例详解

发布时间:2020-12-25 10:29:58 所属栏目:经验 来源:网络整理
导读:C++中友元的实例详解 尽管友元被授予从外部访问类的私有部分的权限,但他们并不与面向对象的编程思想相悖;相反他提高了公共接口的灵活性。 一、友元类 友元声明可以位于公有、私有活保护部分、其所在位置无关紧要 我直接贴出一个摘自 c++ primer plus 的例
副标题[/!--empirenews.page--]

C++中友元的实例详解

尽管友元被授予从外部访问类的私有部分的权限,但他们并不与面向对象的编程思想相悖;相反他提高了公共接口的灵活性。

一、友元类

友元声明可以位于公有、私有活保护部分、其所在位置无关紧要

我直接贴出一个摘自< c++ primer plus >的例子来演示 c++ 友元类

其中 Remote 为 Tv的友元类。

Tv.h

#ifndef TV_H_
#define TV_H_

/*一个类 电视 */
class Tv
{
public:
  friend class Remote; //Remote类可以访问Tv Privite 的私有部分
  enum {
    off,on  //开关 
  };
  enum 
  {
    MinVal,MaxVal=20  //音量
  };
  enum {
    Antena,Cable //使用的天线、还是电缆
  };
  enum 
  {
    TV,DVD  //工作模式
  };

  Tv(int s = off,int mc = 125) :state(s),volume(5),maxchannel(mc),channel(5),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 == Antena) ? Cable : Antena; }
  void set_input() { input = (input == TV) ? DVD : TV; }
  void settings()const; //显示所有设置


private:
  int state;  // 开或者 关
  int volume; // 音量
  int maxchannel; //最大
  int channel;  //当前频道
  int mode;  // 广播还是 电缆
  int input; //Tv 或者 DVD
};

/*Remote 的定义 (遥控器) */
class Remote {
private :
  int mode; // 控制 TV 或 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) { return t.onoff(); }
  void chanup(Tv & t) { return t.chanup(); }
  void chandown(Tv & t) { return t.chandown(); }
  void set_chan(Tv &t,int c) { t.channel = c; } //访问了Tv的私有成员
  void set_mode(Tv &t) { t.set_mode(); }
  void set_input(Tv &t) { t.set_input(); }
};
#endif // TV_H_

Tv.cpp

#include "stdafx.h"
#include "Tv.h"
#include <iostream>

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 == Antena ? "antenna" : "cable") << endl;
    cout << "Input = " << (input == TV ? "TV" : "DVD") << endl;
  }
}

测试代码:

#include "stdafx.h"
#include "tv.h"
#include <iostream>

int main()
{
  using std::cout;
  Tv s42;
  cout << "Initial settings for 42 " Tv: n";
  s42.settings();
  s42.onoff();
  s42.chanup();

  cout << " n Adjusted settings for 42 " Tv: n";
  s42.chanup();
  cout << "n Adjusted settings for 42 " Tv: n";
  s42.settings();

  Remote grey;
  grey.set_chan(s42,10);
  grey.volup(s42);
  grey.volup(s42);
  cout << " n s42 " settings after using remote: n";
  s42.settings();

  Tv s58(Tv::on);
  s58.set_mode();
  grey.set_chan(s58,58);
  cout << " n s58 " setting: n";
  s58.settings();

  system("pause");
  return 0;
}

运行结果:

Initial settings for 42 " Tv:
TV is off

 Adjusted settings for 42 " Tv:

 Adjusted settings for 42 " Tv:
TV is on
Volume setting =5
Channel setting = 7
Mode = cable
Input = TV

 s42 " settings after using remote:
TV is on
Volume setting =7
Channel setting = 10
Mode = cable
Input = TV

 s58 " setting:
TV is on
Volume setting =5
Channel setting = 58
Mode = antenna
Input = TV
请按任意键继续. . .

上述代码中将Remote类设置成为了Tv类的友元类,但事实上我们看到:唯一访问Tv的成员的方法是void set_chan(Tv &t,int c) { t.channel = c; } ,因此它是唯一需要友元的方法。因此不必让整个类成为友元,这就引出了我们下面要讲的的友元成员函数。

二、友元成员函数

我们要再Tv中将Remote::set_chan()设置成友元:

clas Tv
{
  friend void Remote::set_chan(Tv & t,int c ) ;
}

然而要使编译器能够处理这条语句,它必须知道Remote的定义。否则,它无法知道Remote是一个类。而 set_chan是这个类的方法。这意味着应将Remote的定义放到Tv的定义前面。Remote的方法提到了Tv对象,而意味着Tv定义应当位于Remote定义之前,避开这种循环依赖的方法是,使用前向声明。
所以应该这样:

class Tv ; //前向声明
class Remote{...}
class Tv {...}

这里还有一个麻烦就是:

Remote 包含了内联代码例如:void onoff(Tv &t) {t.onoff();};

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读