您的位置:首页 > 编程语言 > C语言/C++

C++友元类讲解

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

在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中那么繁琐。并且在链表类中完全都是直接访问链表结点类的成员数据,大大减少了调用函数产生的开销,这样执行程序的效率也就得以提高了。

原文:http://see.xidian.edu.cn/cpp/biancheng/view/87.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: