面向对象编程的类的设计机制实现了数据的隐藏与封装,类的成员变量一般定义为私有成员,成员函数一般定义为公有的,是类与外部的通信接口。在实践中,类外的某些函数需要频繁地访问类的成员变量,可以将类外的函数定义为类的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但友元破坏了类的封装性和隐藏性,使得非类的成员函数可以访问类的私有成员。
友元是C++语言中的一种关系,友元关系发生在函数与类之间或者类与类之间。友元关系是单向的,不能传递。
与类有友元关系的函数称为友元函数,与类有友元关系的类称为友元类。
友元的特性如下:
A、在类中以friend关键字声明友元
B、类的友元可以是其它类或具体函数
C、友元不是类的一部分
D、友元不受类中访问级别的限制
E、友元可以直接访问具体类的所有成员
F、友元关系不能被继承
G、友元关系是单向的,不具交换性
H、友元关系不具有传递性
友元的本质,是让其它不属于本类的成员(全局函数,其它类的成员函数,其它类),成为本类的成员而具备本类成员的属性。
友元函数是可以直接访问类的私有成员的非成员函数,是定义在类外的函数,可以是不属于任何类的全局函数或是其它类的成员函数,但需要在类的定义中加以声明。
全局函数作为类的友元声明时只需在友元的名称前加上关键字friend,其格式如下:friend 类型 函数名(形式参数);
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
#include <iostream>
#include <cmath>
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;
}
类成员函数作为类的友元声明时只需在友元的名称前加上关键字friend,其格式如下:friend 类型 类名::函数名(形式参数);
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
#include <iostream>
#include <cmath>
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 <iostream>
#include <cmath>
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的私有成员和保护成员。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。