C++教程:C++友元類講解
2020-05-23 14:25:46
供稿:網友
在編寫鏈表類的時候我們有著這樣的困惑:鏈表類和鏈表結點類都是我們編寫的,我們能保證鏈表類對鏈表結點類的操作都是安全的。但由于類的封裝性,我們不得不編寫一些成員函數,以便于鏈表類訪問鏈表結點類的私有成員數據。好在鏈表結點類的成員數據并不是很多,否則豈不是需要一大堆成員函數來供別的類訪問?對于這種情況,我們能否告訴鏈表結點類:“鏈表類是安全的,讓它訪問你的私有成員吧”?
在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中那么繁瑣。并且在鏈表類中完全都是直接訪問鏈表結點類的成員數據,大大減少了調用函數產生的開銷,這樣執行程序的效率也就得以提高了。