友元函数的基本概念
1、概念:可以在类A中通过关键字friend声明或定义某个独立函数或另一个类B的某个成员函数或另一个类B为类A的友元函数,友元函数可以无限制的存取类A的成员(包括私有、公有和保护成员)。
2、定义形式:friend 函数类型 函数所在类名::函数名(参数列表);
3、友元函数可在类中的私有或公有部分通过关键字friend说明或定义,但如在类中声明,而在类外定义,就不能再在类外使用friend关键字。友元函数作用域的开始点在它的说明点,结束点和类的作用域相同。
4、友元函数应被看作类的接口的一部分,使用它的主要目的是提高效率,因为它可以直接访问对象的私有成员,从而省去调用类的相应成员函数的开销。友元函数的另一个优点是:类的设计者不必在考虑好该类的各种可能使用情况之后再设计这个类,而是可以根据需要,通过使用友元来增加类的接口。
一、类外的独立函数作为类的友元函数
类外的独立函数作为类的友元函数,这个独立函数其实就是一个普通的函数,仅有的不同点是:它在类中被说明为类的友元函数,可以访问该类所有对象的私有成员。
【例1】使用友元函数计算两点距离的例子
#include <iostream>
#include <cmath>
using namespace std;
class Point {
private:
double X,Y;
public:
Point( double xi,double yi){X=xi,Y=yi;} //类Point的构造函数
double GetX( ){return X;}
double GetY( ){return Y;}
friend double distances( Point&, Point&); //声明友元函数
};
double distances( Point& a, Point& b)
//像普通函数一样定义友元函数,传引用的方式不会产生临时对象
{ double dx=a.X-b.X; //因是友元函数,所以可以直接访问对象的私有数据成员
double dy=a.Y-b.Y; //因是友元函数,所以可以直接访问对象的私有数据成员
return sqrt( dx*dx + dy*dy );
}
void main( ){
Point p1(3.5,5.5),p2(4.5,6.5);
//定义Point类的对象p1和p2,并调用Point类的构造函数对其初始化
Cout<<"The distance is"<<distances(p1,p2)>>endl;
//调用函数distances,实现dx、dy和两点距离的计算并返回后输出
} //程序结束,析构Point类的对象p1和p2。
二、类B的成员函数作为类A的友元函数
一个类的成员函数(包括构造函数和析构函数)可以通过使用friend说明为另一个类的友元函数。
【例2】类One的对象通过友元函数访问类Two的对象的私有数据
#include <iostream>
using namespace std;
class Two; //先声明类Two,以便类One引用Two&
class One {
private:
int x;
public:
One(int a){x=a;} //定义类One的构造函数
int Getx( ){return x;} //定义普通成员函数
void func(Two&); //声明本类的成员函数,参数为类Two的引用
};
class Two{
private:
int y;
public:
Two(int b){y=b;} //定义类Two的构造函数
int Gety( ){return y;} //定义普通成员函数
friend void One::func(Two&); //声明类One的成员函数为本类的友元函数
};
void One::func(Two& r) {r.y=x;} /*定义函数func,以类Two对象的引用为参数。因其是类One的成员函数,所以可自由存取所在类One的私有数据成员;因其在类Two中被声明为友元函数,所以可使用对象名存取类Two的私有数据成员(r.y=x即说明了这些)*/
void main( ){
One Obj1(5); //定义类One的对象Obj1并调用其构造函数初始化Obj1.x为5
Two Obj2(8); //定义类Two的对象Obj2并调用其构造函数初始化Obj2.y为8
Cout<<Obj1.Getx( )<<" "<<Obj2.Gety( )<<endl; //输出:5 8
Obj1.func(Obj2); /*调用函数func将Obj2的地址传给r,执行函数体内语句,将Ojb1的私有数据成员x的值赋给Obj2的私有数据成员y,y的值变为5,x的值不变仍为5*/
Cout<<Obj1.Getx( )<<" "<<Obj2.Gety( )<<endl; //输出:5 5
}
//程序结束,调用类Two的默认析构函数析构对象Obj2,然后调用类One的默认析构函数析构对象Obj1。
三、将一个类说明为另一个类的友元
可以将一个类One说明为另一个类Two的友元,这时,整个类One的成员函数均是类Two的友元函数,声明语句简化为:friend class 类名;。
【例3】类One的对象可以通过任意一个成员函数访问类Two的对象的私有数据
#include <iostream>
using namespace std;
class Two{
int y; //默认为private
public:
friend class One; //声明类One为类Two的友元
};
class One{ //类One的成员函数均是类Two的友元函数
int x; //默认为private
public:
One(int a,Two&r,int b){x=a;r.y=b;} //利用类One的构造函数给本类及类Two的对象赋值
void Display(Two&); //声明类One的成员函数,它能访问类Two的成员
};
void One::Display(Two&r) //定义类One的成员函数,输出类Two的的成员
{cout<<x<<" "<<r.y<<endl;}
void main( ){
Two Obj2; // 定义类Two的成员obj2
One Obj1(23,Obj2,55); /* 定义类One的成员obj1并调用One的构造函数给本类及类Two的对象赋值:obj1.x=23,obj2.y=55 */
Obj1.Display(Obj2); /* 调用定义类One的成员函数Display输出Obj1的私有数据成员x的值和Obj2的私有数据成员y的值,输出:23 55 */
} //程序结束,先后执行类One和类Two的默认析构函数,析构对象Obj1和Obj2。
来源:https://www.cnblogs.com/ruanchunyi/p/10549466.html