C++ Primer Plus 学习笔记 第十五章 友元类 友元成员函数 其他友元关系 共同的友元 嵌套类

本文深入探讨了C++中的友元函数概念,包括如何使特定成员函数成为友元,解决友元类与被友元类之间的相互依赖问题,以及通过前向声明和正确代码组织实现这一目标的方法。同时,文章还介绍了嵌套类的定义、作用域和访问控制,通过实例展示了嵌套类的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

与友元函数类似。

代码:

tv.h

#ifndef TV_H_
#define TV_H_

class Tv
{
  public:
// 这就是友元类的写法
    friend class Remote;
    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() {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;

  private:
    int state;
    int volume;
    int maxchannel;
    int channel;
    int mode;
    int input;
};

class Remote
{
  private:
    int mode;
  public:
    Remote(int m = Tv::TV) : mode(m){}
    bool volup(Tv & t) {return t.volup();}
    bool voldown(Tv & t) {return t.voldown();}
    void cnoff(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

这里面那么多的函数 只有1个函数涉及到了友元,那能不能让特定的成员函数成为友元呢? 可以:

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

光这样写还不行  要让编译器事先知道Remote是啥 但是, 又有一个问题 Remote中有涉及到了Tv类,那也要事先让编译器知道Tv类是啥; 这就蛋疼了,咋搞?

使用前向声明

class Tv;

class Remote {....};

class Tv{...};

这样排列后还是有一个问题,就是Remote中很多函数时内联函数,也就是说提前调用了Tv类的函数。那编译器依然找不到对应的函数。咋办?

Remote类中涉及调用Tv类的成员的部分 放到Tv类定义的代码段后面写。就可以了

上示例吧:

#ifndef TV_H_
#define TV_H_

// 先声明
class Tv;

class Remote
{
  public:
    enum {Off, On};
    enum {MinVal, MaxVal = 20};
    enum {Antenna, Cable};
    enum {TV, DVD};
  private:
    int mode;
  public:
    Remote(int m = TV) : mode(m){}
    bool volup(Tv & t);
    bool voldown(Tv & t);
    void cnoff(Tv & t);
    void chanup(Tv & t);
    void chandown(Tv & t);
    void set_chan(Tv & t, int c);
    void set_mode(Tv & t);
    void set_input(Tv & t);
};

// 再详细声明
class Tv
{
  public:
// 特定友元函数
    friend void Remote::set_chan(Tv & t, int c);
    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() {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;

  private:
    int state;
    int volume;
    int maxchannel;
    int channel;
    int mode;
    int input;
};

// 最后定义内联函数
inline bool Remote::volup(Tv & t) {return t.volup();}
inline bool Remote::voldown(Tv & t) {return t.voldown();}
inline void Remote::cnoff(Tv & t) {t.onoff();}
inline void Remote::chanup(Tv & t) {t.chanup();}
inline void Remote::chandown(Tv & t) {t.chandown();}
inline void Remote::set_mode(Tv & t) {t.set_mode();}
inline void Remote::set_input(Tv & t) {t.set_input();}
inline void Remote::set_chan(Tv & t, int c) {t.channel = c;}
#endif

其他友元关系:

如果Tv类成为Remote的友元。那有一点要注意  在Tv类中调用了Remote类的相关成员或成员函数  一定要写在Remote类详细声明的后面。(先来后到 不然编译器无法识别Remote是啥玩意儿,这个跟刚才那个友元成员函数是一个情况)

共同的友元

这个没啥内容 就是弄一个内联函数 然后成为两个或者多个类的友元函数就是了

这里有句话很关键

嵌套类

嵌套类定义格式

嵌套类的作用域:

访问控制:

模板中的嵌套

其实就是内部类啦

形象的表示就是人的器官 也是类 但是是在人这个类的内部

上代码:

queuetp.h

#ifndef QUEUETP_H_
#define QUEUETP_H_

template<class Item>
class QueueTP
{
  private:
    enum {Q_SIZE = 10};
    class Node
    {
      public:
        Item item;
        Node * next;
        Node(const Item & i) : item(i), next(0) {}
    };
    Node * front;
    Node * rear;
    int items;
    const int qsize;
    QueueTP(const QueueTP & q) : qsize(0) {}
    QueueTP & operator=(const QueueTP & q) {return *this;}
  public:
    QueueTP(int qs = Q_SIZE);
    ~QueueTP();
    bool isempty() const
    {
      return items == 0;
    }
    bool isfull() const
    {
      return items == qsize;
    }
    int queuecount() const
    {
      return items;
    }
    bool enqueue(const Item & item);
    bool dequeue(Item & item);
};

template<class Item>
QueueTP<Item>::QueueTP(int qs) : qsize(qs)
{
  front = rear = 0;
  items = 0;
}

template<class Item>
QueueTP<Item>::~QueueTP()
{
  Node * temp;
  while(front != 0)
  {
    temp = front;
    front = front-> next;
    delete temp;
  }
}

template<class Item>
bool QueueTP<Item>::enqueue(const Item & item)
{
  if (isfull())
    return false;
  Node * add = new Node(item);
  items++;
  if (front == 0)
    front = add;
  else
    rear->next = add;
  rear = add;
  return true;
}

template<class Item>
bool QueueTP<Item>::dequeue(Item & item)
{
  if (front == 0)
    return false;
  item = front->item;
  items--;
  Node * temp = front;
  front = front -> next;
  delete temp;
  if (items == 0)
    rear = 0;
  return true;
}

#endif

nested.cpp

#include <iostream>
#include "queuetp.h"

int main()
{
  using std::string;
  using std::cin;
  using std::cout;

  QueueTP<string> cs(5);
  string temp;

  while(!cs.isfull())
  {
    cout << "Please enter your name. You will be "
            "served in the order of arrival.\n"
            "name: ";
    getline(cin, temp);
    cs.enqueue(temp);
  }
  cout << "The queue is full. Processing begins!\n";

  while (!cs.isempty())
  {
    cs.dequeue(temp);
    cout << "Now processing " << temp << "...\n";
  }
  return 0;
}

完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@凌晨三点半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值