c++中的类具有封装性,类中的私有数据只有该类的成员函数可以访问,程序中访问类中的私有成员,必须通过对象来调用成员函数,但是频繁的调用会使运行效率降低。
为了解决上述问题,c++中加入友元机制,友元可以不通过调用成员函数直接访问类的私有数据来提高运行效率。
友元可以是函数(友元函数)也可以是类(友元类)
友元函数:
- 类体内说明,加friend关键字,在类体外定义,定义格式和普通函数相同。
- 友元函数是非成员函数,调用上和普通函数相同。
- 友元函数可以直接访问类中私有成员。
全局或函数做友元函数:
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 class Point 5 { 6 public: 7 Point(double xx, double yy) 8 { 9 x = xx; 10 y = yy; 11 } 12 void Getxy(); 13 friend double Distance(Point &a, Point &b); 14 private: 15 double x, y; 16 }; 17 void Point::Getxy() 18 { 19 cout << "(" << x << "," << y << ")" << endl; 20 } 21 double Distance(Point &a, Point &b) 22 { 23 double dx = a.x -‐ b.x; 24 double dy = a.y -‐ b.y; 25 return sqrt(dx*dx + dy*dy); 26 } 27 int main(void) 28 { 29 Point p1(3.0, 4.0), p2(6.0, 8.0); 30 p1.Getxy(); 31 p2.Getxy(); 32 double d = Distance(p1, p2); 33 cout << "Distance is " << d << endl; 34 return 0; 35 }
类成员函数做友元函数:
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 class Point; 5 //前向声明,是⼀一种不完全型声明,即只需提供类名(⽆无需提供类实现)即可。仅可⽤用 于声明指针和引 6 ⽤用。 7 class ManagerPoint 8 { 9 public: 10 double Distance(Point &a, Point &b); 11 }; 12 class Point 13 { 14 public: 15 Point(double xx, double yy) 16 { 17 x = xx; 18 y = yy; 19 } 20 void Getxy(); 21 friend double ManagerPoint::Distance(Point &a, Point &b); 22 private: 23 double x, y; 24 }; 25 void Point::Getxy() 26 { 27 cout << "(" << x << "," << y << ")" << endl; 28 } 29 double ManagerPoint::Distance(Point &a, Point &b) 30 { 31 double dx = a.x -‐ b.x; 32 double dy = a.y -‐ b.y; 33 return sqrt(dx*dx + dy*dy); 34 } 35 int main(void) 36 { 37 Point p1(3.0, 4.0), p2(6.0, 8.0); 38 p1.Getxy(); 39 p2.Getxy(); 40 ManagerPoint mp; 41 float d = mp.Distance(p1,p2); 42 cout << "Distance is " << d<< endl; 43 return 0; 44 }
友元类:
- 友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息
- 格式;friend class 友元类名
- 当说明一个类A是另一个类B的友元时,友元类A中所有成员函数都是另一个类B的友元函数
1 #include <iostream> 2 3 using namespace std; 4 5 class X{ 6 public: 7 friend class Y; //类Y 是类X 的友元类 8 void set(int i) { x=i; } 9 void display() 10 { 11 cout<<"x="<<x<<","<<"y="<<y<<endl; 12 } 13 private: 14 int x; 15 static int y; //静态数据说明 16 }; 17 18 class Y 19 { 20 public: 21 Y(int i,int j); 22 void display(); 23 private: 24 X a; //数据成员为类X的对象 25 }; 26 27 int X::y=10; //静态数据定义并初始化 28 29 Y::Y(int i,int j) 30 { 31 a.x=i; X::y=j; 32 } 33 34 void Y::display() 35 { 36 cout<<"x="<<a.x<<","<<"y="<<X::y<<endl; 37 } 38 39 int main() 40 { 41 X b; 42 b.set(5); 43 b.display(); 44 Y c(6,9); 45 c.display(); 46 b.display(); 47 return 0; 48 }
总结:
- 友元虽然提高了代码的运行效率,但是他破坏了类的封装性。
- 友元关系不可以被继承
- 友元关系是单向的,没有交换性
- 友元关系没有传递性