您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

C++友元类讲解

时间:01-10来源:作者:点击数:

在编写链表类的时候我们有着这样的困惑:链表类和链表结点类都是我们编写的,我们能保证链表类对链表结点类的操作都是安全的。但由于类的封装性,我们不得不编写一些成员函数,以便于链表类访问链表结点类的私有成员数据。好在链表结点类的成员数据并不是很多,否则岂不是需要一大堆成员函数来供别的类访问?对于这种情况,我们能否告诉链表结点类:“链表类是安全的,让它访问你的私有成员吧”?

在C++中,可以用友元来解决这种尴尬的问题。所谓友元,就是作为一个类的“朋友”,可以例外地访问它的私有成员数据或私有成员函数。

友元类

类似于链表类和链表结点类的问题,我们可以用友元类来解决。即链表类是链表结点类的“朋友”,可以直接访问链表结点类的私有成员数据或私有成员函数。显然,要做链表结点类的“朋友”,必须要得到链表结点类的认可。所以我们必须在链表结点类的声明中告诉电脑,链表类是它认可的“朋友”,可以访问它的私有成员。声明友元类的语句格式为:
    friend class 类名;

下面我们来看一下,友元是如何让我们更方便地设计程序的:(程序16.2.1)

//node.h

class Node//声明一个链表结点类
{
   friend class Linklist;//在Node类中声明友元类Linklist
   public:
   Node();
   Node(Node &n);
   Node(int i,char c='0');
   Node(int i,char c,Node *p,Node *n);
   ~Node();
   static int allocation();
   private:
   int idata;
   char cdata;
   Node *prior;
   Node *next;
   static int count;
};

//node.cpp

#include "node.h"
#include <iostream>
using namespace std;
int Node::count=0;
Node::Node()
{
   cout <<"Node constructor is running..." <<endl;
   count++;
   idata=0;
   cdata='0';
   prior=NULL;
   next=NULL;
}
Node::Node(int i,char c)
{
   cout <<"Node constructor is running..." <<endl;
   count++;
   idata=i;
   cdata=c;
   prior=NULL;
   next=NULL;
}
Node::Node(int i,char c,Node *p,Node *n)
{
   cout <<"Node constructor is running..." <<endl;
   count++;
   idata=i;
   cdata=c;
   prior=p;
   next=n;
}
Node::Node(Node &n)
{
   count++;
   idata=n.idata;
   cdata=n.cdata;
   prior=n.prior;
   next=n.next;
}
Node::~Node()
{
   count--;
   cout <<"Node destructor is running..." <<endl;
}
int Node::allocation()
{
   return count;
}

//linklist.h

#include "node.h"
#include <iostream>
using namespace std;
class Linklist//定义一个链表类
{
   public:
   Linklist(int i,char c);
   Linklist(Linklist &l);
   ~Linklist();
   bool Locate(int i);
   bool Locate(char c);
   bool Insert(int i=0,char c='0');
   bool Delete();
   void Show();
   void Destroy();
   private:
   Node head;
   Node * pcurrent;
};
Linklist::Linklist(int i,char c):head(i,c)//链表的构造函数
{
   cout<<"Linklist constructor is running..."<<endl;
   pcurrent=&head;
}
Linklist::Linklist(Linklist &l):head(l.head)
{
   cout<<"Linklist Deep cloner running..." <<endl;
   pcurrent=&head;
   Node * ptemp1=l.head.next;//直接访问私有成员数据
   while(ptemp1!=NULL)
   {
      Node * ptemp2=new Node(ptemp1->idata,ptemp1->cdata,pcurrent,NULL);
      pcurrent->next=ptemp2;
      pcurrent=pcurrent->next;
      ptemp1=ptemp1->next;
}
}
Linklist::~Linklist()
{
   cout<<"Linklist destructor is running..."<<endl;
   Destroy();
}
bool Linklist::Locate(int i)
{
   Node * ptemp=&head;
   while(ptemp!=NULL)
   {
      if(ptemp->idata==i)
      {
         pcurrent=ptemp;
         return true;
      }
      ptemp=ptemp->next;
   }
   return false;
}
bool Linklist::Locate(char c)
{
   Node * ptemp=&head;
   while(ptemp!=NULL)
   {
      if(ptemp->cdata==c)
      {
         pcurrent=ptemp;
         return true;
      }
      ptemp=ptemp->next;
   }
   return false;
}
bool Linklist::Insert(int i,char c)
{
   if(pcurrent!=NULL)
   {
      Node * temp=new Node(i,c,pcurrent,pcurrent->next);
      if (pcurrent->next!=NULL)
      {
         pcurrent->next->prior=temp;
      }
      pcurrent->next=temp;
      return true;
   }
   else
   {
      return false;
   }
}
bool Linklist::Delete()
{
   if(pcurrent!=NULL && pcurrent!=&head)
   {
      Node * temp=pcurrent;
      if (temp->next!=NULL)
      {
         temp->next->prior=pcurrent->prior;
      }
      temp->prior->next=pcurrent->next;
      pcurrent=temp->prior;
      delete temp;
      return true;
   }
   else
   {
      return false;
   }
}
void Linklist::Show()
{
   Node * ptemp=&head;
   while (ptemp!=NULL)
   {
      cout <<ptemp->idata <<'\t' <<ptemp->cdata <<endl;
      ptemp=ptemp->next;
   }
}
void Linklist::Destroy()
{
   Node * ptemp1=head.next;
   while (ptemp1!=NULL)
   {
      Node * ptemp2=ptemp1->next;
      delete ptemp1;
      ptemp1=ptemp2;
   }
   head.next=NULL;
}

//main.cpp 同程序16.1

运行结果:
请输入一个整数和一个字符:
3 F
Node constructor is running...
Linklist constructor is running...
Node constructor is running...
Node constructor is running...
After Insert
3 F
2 B
1 C
Node Allocation:3
Node constructor is running...
An independent node created
Node Allocation:4
Node destructor is running...
Linklist destructor is running...
Node destructor is running...
Node destructor is running...
Node destructor is running...

可以看到,程序的运行结果和程序16.1的结果一样,但是链表结点类没有程序16.1中那么繁琐。并且在链表类中完全都是直接访问链表结点类的成员数据,大大减少了调用函数产生的开销,这样执行程序的效率也就得以提高了。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门