在C++中,为了使类的私有成员和保护成员能被其它类或其它成员函数访问,引入的友元的概念。
友元函数
友元函数定义后可以访问改类的所有对象的所有成员,包括private、protected、public成员。友元函数使用前必须要在类定义时声明,声明时在其函数名前加上关键字friend。该声明可以放在公有成员中,也可以放在私有成员中。友元函数可以在类内部定义,也可以在类外部定义,通常在类外部定义。使用友元函数注意事项:
1.友元函数不是成员函数,定义时不必加::。
2.友元函数不是类的成员,因而不真直接引用对象的名字,也不能通过this指针引用对象的成员,必须通过作为入口参数传递进来的对象名或对象指针来引用该对象的成员。因些,友元函数一般都带有一个该函数的入口参数,如下例中的area(Rec &rec)。
3.当一个函数需要访问多个类时,应该把这个函数同时定义为为些类的友元函数。
友元函数声明: friend<数据类型><友元函数名>(参数表);
#include<iostream>
using namespace std;
class Rec{
double len,wid;//私有成员
public:
Rec(double a=0,double b=0);
Rec(Rec &r);
friend double area(Rec &rec);//声明友元函数
};
Rec::Rec(double a,double b)
{
len=a ;
wid=b;
}
double area(Rec &rec)
{
return rec.len*rec.wid;//友元访问私有成员
}
int main()
{
Rec r1(3,4);
cout<<area(r1)<<endl;
system("pause");
}
友元成员
如果一个类的成员函数是另一个类的友元函数,则称这个成员函数为友元成员。通过友元成员,不仅可以访问自己所在的类对象中的所有其他成员,还可以访问由关键字friend声明语句所在的类的对象中的所有成员。这种机制可以让两个类相互访问,从而共同完成某些特定任务。例:
#include<iostream>
#include<string>
using namespace std;
class boy;//声明boy类
class girl
{
char *name;
int age;
public:
girl(char *n,int a)
{
name = new char[strlen(n)+1];
strcpy(name,n);
age = a;
}
void prt(boy &b);
~girl()
{
delete name;
}
};
class boy{
char *name;
int age;
public:
boy(char *n,int a)
{
name = new char[strlen(n)+1];
strcpy(name,n);
age = a;
}
friend void girl::prt(boy &b); //声明友元成员。在声明友元函数时,要加上成员函数所在类的类名和作用域运算符::。
~boy()
{
delete name;
}
};
void girl::prt(boy &b)//定义友元成员。 这里不能直接放在girl类后面,否则会报错。
{
cout<<"girl\'s name: "<<name<<" age:"<<age<<endl;
cout<<"boy\'s name: "<<b.name<<" age:"<<b.age<<endl;
}
int main()
{
girl g1("Hanmeimei",15);
boy b1("Lilei",16);
g1.prt(b1);
system("pause");
}
注意:
1.当一个类的成员函数作为另一个类的友元函数时,必须先定义成员函数所在的类,如上述代码中的girl的成员函数prt()为类boy的友元函数,就必须先定义类girl,并且ptr要在boy之后定义。
2.在声明友元函数时,要加上成员函数所在类的类名和作用域运算符::。
友元类
如果一个类作为另一个类的友元,称这个类为友元类。当一个类成为另一个类的友元类时,这个类的所有成员函数都成为另一个类的友元函数。友元类中的所有成员函数都可以通过对象名直接访问另一个类的所有成员,从而实现不同类之间的数据共享。
#include<iostream>
#include<string>
using namespace std;
class boy;//声明boy类
class girl
{
char *name;
int age;
public:
girl(char *n,int a)
{
name = new char[strlen(n)+1];
strcpy(name,n);
age = a;
}
void prt(boy &b);
~girl()
{
delete name;
}
};
class boy{
char *name;
int age;
public:
boy(char *n,int a)
{
name = new char[strlen(n)+1];
strcpy(name,n);
age = a;
}
friend class girl; //声明友元成员,加上成员函数所在的类名和::
~boy()
{
delete name;
}
};
void girl::prt(boy &b)//定义友元成员。 这里不能直接放在girl类后面,否则会报错。
{
cout<<"girl\'s name: "<<name<<" age:"<<age<<endl;
cout<<"boy\'s name: "<<b.name<<" age:"<<b.age<<endl;
}
int main()
{
girl g1("Hanmeimei",15);
boy b1("Lilei",16);
g1.prt(b1);
system("pause");
}
boy类的定义中,将girl类声明为boy类的友元类,因此,girl类的成员可以访问boy类的所有成员。
注意:
1.友元关系是不能传递的。类B是类A的友元,类C是类B的友元,但类C与类A无关系。
2.友元关系也是单向的。类B是类A的友元,类B的成员函数可以访问类A的所有成员,但是类A不可以访问类B的private和protected成员。