目录
一.友元分为友元函数和友元类
友元函数:一个类的友元函数可以访问该类的私有成员
友元类 :如果A是B的友元类,那么A的成员函数可以访问B的私有成员
二.为什么要用友元函数
1. 类的私有成员是不允许类外的任何函数和外部类存取的,可以引入友元函数,是为在该类中提供一个对外(除了它自己以外)访问的窗口
2.注意:友元函数不是类的成员,不属于任何类
3.友元函数不属于该类的成员函数,它是定义在类外的普通函数,只是类中声明该函数可以直接访问类中的private或者protected成员
三.友元函数的定义和声明
friend 类型 函数名 (参数)
例如: friend int addFive(Distance)
//代码举例1
#include <iostream>
using namespace std;
class Distance{
int meter;
public:
Distance(): meter(0){}
friend int addFive(Distance);//用friend表明addFive函数是类Distance的友元
};
int addFive(Distance d)//该函数在类内声明,类外定义
{
d.meter= 5;//访问了类内的私有成员
return d.meter;
}
int main(){
Distance D;
cout<<"Distance: "<< addFive(D);
return 0;
}
//代码举例2:一个友元函数可以访问两个类的私有成员
#include <iostream>
using namespace std;
class B;
class A {
int numA;
public:
A(): numA(12) { }//将12赋值给numA,之后private中的numA为12
friend int add(A, B);
};
class B {
int numB;
public:
B(): numB(1) { }//将1赋值给numB,之后private中的numB为1
friend int add(A , B);//and函数可以访问A,B的私有成员
};
int add(A objectA, B objectB){
return (objectA.numA + objectB.numB);
}
int main(){
A objectA;
B objectB;
cout<<"Sum: "<< add(objectA, objectB);
return 0;
}
//代码举例2.2 :一个友元函数可以访问两个类的私有成员
#include <iostream>
using namespace std;
class B;
class A {
int numA;
public:
A(int x): numA(x) { }//A接收传进来的x,然后x赋值给numA
//之后private中的numA为12
friend int add(A, B);
};
class B {
int numB;
public:
B(int y): numB(y) { }
friend int add(A , B);
};
int add(A objectA, B objectB){
return (objectA.numA + objectB.numB);
}
int main(){
A objectA(12);
B objectB(1);
cout<<"Sum: "<< add(objectA, objectB);
return 0;
}
//代码举例3:友元函数和拷贝构造函数
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
private:
int X, Y;
public:
Point(int xx = 0, int yy = 0)
{
X = xx; Y = yy;
}
int GetX()
{
return X;
}
int GetY()
{
return Y;
}
friend double fDist( Point , Point );
//等价形式friend double fDist( Point a, Point b);
Point(const Point &)
{
cout<<"拷贝构造函数--->"<<endl;
}
};
double fDist(Point p1, Point p2)//p1和p2是形参
{
double x = double(p1.X - p2.X);
double y = double(p1.Y - p2.Y);
return double(sqrt(x*x + y*y));
}
int main()
{
Point a(2, 3), b(4, 5);
cout << "the distance is:"<<endl;;
cout << fDist(a, b) << endl;//调用fDist()函数,将a传给A,b传给B,是实参到形参的拷贝,会调用拷贝构造函数
return 0;
}
//代码举例3.1:友元函数和引用
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point(int xx = 0, int yy = 0)
{
X = xx; Y = yy;
}
int GetX()
{
return X;
}
int GetY()
{
return Y;
}
friend double fDist( Point &, Point &);//使用引用以后,没有调用拷贝构造函数
//等价形式friend double fDist( Point &p1, Point &p2);
Point(const Point &)
{
cout<<"拷贝构造函数--->"<<endl;
}
private:
int X, Y;
};
double fDist(Point &p1, Point &p2)
{
double x = double(p1.X - p2.X);
double y = double(p1.Y - p2.Y);
return double(sqrt(x*x + y*y));
}
int main(){
Point a(2, 3), b(4, 5);
cout << "the distance is:"<<endl;;
cout << fDist(a, b) << endl;
return 0;
}
四.友元类
1.友元类的声明和定义
friend class 类名
例如: friend class C
#include <iostream>
using namespace std;
class A
{
private:
int data;
public:
friend class C;//这是友元类的声明
};
class C//友元类定义,为了访问类A中的成员
{
public:
void set_show(int x, A &a)//A & a表示引用,
// int n=4 ; int & r=n; r引用了n,并且r的类型是int &
// A & a,a的类型是A &
{
a.data = x;
cout<<a.data<<endl;
}
};
int main(void)
{
A a;
C c;
c.set_show(1, a);
return 0;
}
2.友元类的注意事项
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。
五.友元成员函数
类A的成员函数是类B的友元函数,该成员函数能够访问类B的所有成员
//代码举例
#include <iostream>
using namespace std;
class B;
class A
{
public:
void showB(B& );//showB()是类A的成员函数
};
class B
{
int b;
public:
B()
{
b = 0;
}
friend void A::showB(B & x);//void A::showB(B& x)表明showB()函数是属于类A,
//而前面再加个friend表明A类中的showB()是类B的友元函数
};
void A::showB(B & x)//在类外定义友元函数
{
cout << "B::b = " << x.b;//访问的是类B的私有成员b
}
int main()
{
A a;
B x;//x是类B的一个对象
a.showB(x);
return 0;
}