C++语言学习(七)——友元
C++语言学习(七)--友元
一、友元简介
1、友元简介
面向对象编程的类的设计机制实现了数据的隐藏与封装,类的成员变量一般定义为私有成员,成员函数一般定义为公有的,是类与外部的通信接口。在实践中,类外的某些函数需要频繁地访问类的成员变量,可以将类外的函数定义为类的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但友元破坏了类的封装性和隐藏性,使得非类的成员函数可以访问类的私有成员。
友元是C++语言中的一种关系,友元关系发生在函数与类之间或者类与类之间。友元关系是单向的,不能传递。
与类有友元关系的函数称为友元函数,与类有友元关系的类称为友元类。
2、友元的特性
友元的特性如下:
A、在类中以friend关键字声明友元
B、类的友元可以是其它类或具体函数
C、友元不是类的一部分
D、友元不受类中访问级别的限制
E、友元可以直接访问具体类的所有成员
F、友元关系不能被继承
G、友元关系是单向的,不具交换性
H、友元关系不具有传递性
3、友元的本质
友元的本质,是让其它不属于本类的成员(全局函数,其它类的成员函数,其它类),成为本类的成员而具备本类成员的属性。
二、友元函数
1、友元函数简介
友元函数是可以直接访问类的私有成员的非成员函数,是定义在类外的函数,可以是不属于任何类的全局函数或是其它类的成员函数,但需要在类的定义中加以声明。
2、全局函数为友元函数
全局函数作为类的友元声明时只需在友元的名称前加上关键字friend,其格式如下:friend 类型 函数名(形式参数);
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
#include #include using namespace std;class Point{public: Point(double x = 0, double y = 0) { this->x = x; this->y = y; } void printPoint() { cout << "(" << x << "," << y << ")"; } //友元函数声明 friend double getDistance(const Point &a, const Point &b);private: double x; double y;};double getDistance(const Point &a, const Point &b){ double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx*dx + dy*dy);}int main(int argc, char *argv[]){ Point a(0,0); Point b(1,8); cout << "Point"; a.printPoint(); cout << " and Point"; b.printPoint(); cout << " has distance at "<< getDistance(a, b) << endl; return 0;}
3、类成员函数为友元函数
类成员函数作为类的友元声明时只需在友元的名称前加上关键字friend,其格式如下:friend 类型 类名::函数名(形式参数);
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
#include #include using namespace std;class Point;class ManagerPoint{public: double getDistance(const Point &a, const Point &b);};class Point{public: Point(double x = 0, double y = 0) { this->x = x; this->y = y; } void printPoint() { cout << "(" << x << "," << y << ")"; } //友元函数声明 friend double ManagerPoint::getDistance(const Point &a, const Point &b);private: double x; double y;};double ManagerPoint::getDistance(const Point &a, const Point &b){ double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx*dx + dy*dy);}int main(int argc, char *argv[]){ ManagerPoint manager; Point a(0,0); Point b(1,8); cout << "Point"; a.printPoint(); cout << " and Point"; b.printPoint(); cout << " has distance at "<< manager.getDistance(a, b) << endl; return 0;}
上述代码中使用了类的前向声明。前向声明,是一种不完全型(forward declaration)声明,即只需提供类名(无需提供类实现)即可。前向声明功能有限:
A、不能定义类的对象。
B、可以用于定义指向这个类型的指针或引用。
C、用于声明(不是定义)使用该类型作为形参或者返回类型的函数。
三、友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以访问另一个类的私有成员、保护成员时,可以将该类声明为另一类的友元类。
定义友元类的语句格式如下:friend class 类名;
friend和class是关键字,类名必须是程序中的一个已定义的类。
#include #include using namespace std;class Point;class ManagerPoint{public: double getDistance(const Point &a, const Point &b);};class Point{public: Point(double x = 0, double y = 0) { this->x = x; this->y = y; } void printPoint() { cout << "(" << x << "," << y << ")"; } //友元类声明 friend class ManagerPoint;private: double x; double y;};double ManagerPoint::getDistance(const Point &a, const Point &b){ double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx*dx + dy*dy);}int main(int argc, char *argv[]){ ManagerPoint manager; Point a(0,0); Point b(1,8); cout << "Point"; a.printPoint(); cout << " and Point"; b.printPoint(); cout << " has distance at "<< manager.getDistance(a, b) << endl; return 0;}
ManagerPoint类的所有成员函数都是类Point的友元函数,能访问类Point的私有成员和保护成员。