C++ 友元
为什么使用友元?
例如:求两点之间的距离
#include <iostream> #include <cmath> class Point //Point类声明 { public: //外部接口 Point(int x=0, int y=0) : x(x), y(y) { } int getX() { return x; } int getY() { return y; } private: //私有数据成员 int x, y; }; float dist( Point& a, Point& b) { double x = a.getX() - b.getX(); double y = a.getY() - b.getY(); return static_cast<float>(sqrt(x * x + y * y)); }
解决方法:设计一个函数计算两点间的距离,解决方案普通函数,成员函数和类的组合都不好,最好采用友元关系。
友元
面向对象程序设计主张程序的封装、数据的隐藏,不过任何事物都不是绝对的,友元打破了这种封装和隐藏。
友元关系提供了一种共享机制,实现不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享。
通俗点举个例子,一个家庭需要通过防盗门窗、门锁、保险柜等措施不让外人接触,但在一些特殊情况下,例如全家出游,又需要检查煤气、水电情况,就不得不把钥匙交给值得依赖的朋友,而这位朋友就是友元。
即通过友元关系,一个普通函数或者类的成员函数可以访问封装于另外一个类的数据。
同时也要明白,友元是C++提供的一种破坏数据封装和数据隐藏的机制。便于实现数据共享,提高程序的效率和可读性。
为了确保数据的完整性及数据封装与隐藏的原则,建议尽量不使用或少使用友元。
在一个类中,可以利用关键字 friend将其他函数或类声明为友元。可以使用友元函数和友元类。
友元函数
如果在本类以外的其他地方定义了一个函数(这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对其进行声明,此函数就称为本类的友元函数。友元函数可以访问这个类中的私有成员和受保护成员。
作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择。
访问对象中的成员必须通过对象名。
UML中由关键字friend修饰。
#include <iostream> #include <cmath> class Point //Point类声明 { public: //外部接口 Point(int x=0, int y=0) : x(x), y(y) { } int getX() { return x; } int getY() { return y; } friend float dist(Point &a, Point &b); private: //私有数据成员 int x, y; }; float dist( Point& a, Point& b) { double x = a.x - b.x; double y = a.y - b.y; return static_cast<float>(sqrt(x * x + y * y)); } int main() { Point p1(1, 1), p2(4, 5); cout <<"The distance is: "; cout << dist(p1, p2) << endl; return 0; }
友元类
不仅可以将一个函数声明为一个类的“朋友”,而且可以将一个类(例如B类)声明为另一个类(例如A类)的“朋友”。这时B类就是A类的友元类。友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。
在A类的定义体中用以下语句声明B类为其友元类:friend B;
声明友元类的一般形式为:
friend 类名;
友元类之间的关系不能传递,不能继承。友元的关系是单向的而不是双向的。进行函数重载时,需要将重载函数集中每一个希望设为友元的函数都声明为友元。
class A { friend class B; public: void display() { cout << x << endl; } private: int x; } class B { public: void set(int i); void display(); private: A a; }; void B::set(int i) { a.x=i; } void B::display() { a.display(); }