C++友元函数、友元类

友元

友元是一种定义在类外部的普通函数或类,需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。
友元提出的原因:
类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
友元函数不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象。

友元函数

在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。友元函数在语法上与普通函数一样,即在定义上和调用上与普通函数一样。
函数声明为友元函数的写法:

  • friend 返回值类型 函数名(参数表);

将其他类的成员函数声明为友元的写法如下:

  • friend 返回值类型 其他类的类名::成员函数名(参数表);

以代码为例体会友元函数的使用:

#include
#include
using namespace std;
class Position
{
public:
    Position(double xx = 0, double yy = 0)
        :_x(xx), _y(yy){};
    void Show() {
        cout << "(" << _x << "," << _y << ")" << endl;
    }
    friend double Distance(Position a, Position b);
private:
    double _x, _y;
};

double Distance(Position a, Position b)
{
    double dx = a._x - b._x;
    double dy = a._y - b._y;
    return sqrt(dx * dx + dy * dy);
}
int main(void)
{
    Position p1(3.0, 4.0), p2(6.0, 8.0);
    p1.Show();
    p2.Show();
    double d = Distance(p1, p2);
    cout << "两点间距离:" << d << endl;
    return 0;
}
  • 在该程序中的position类中声明了一个友元函数Distance(),它在声明时前边加friend关键字,标识它不是成员函数,而是友元函数。它的定义方法与普通函数定义一样。友元函数不是成员函数,但是它可以使用类中的私有成员,函数体中a._x,b._x,a._y,b._y都是类的私有成员。

  • 在调用友元函数时,也是同普通函数的调用一样。程序中,p1.Show()和p2.Show()这是成员函数的调用,要用对象来表示。而Distance(p1, p2)是友元函数的调用,它直接调用,不需要对象表示,它的参数是对象。

友元类

一个类 A 可以将另一个类 B 声明为自己的友元,类 B 的所有成员函数就都可以访问类 A 对象的所有成员。在类定义中声明友元类的写法如下:

  • friend class 类名;

#include
class Hospital
{
public:
    Hospital()
        :_price(100){}
    void Registration() {
        std::cout <<"医院挂号价格:" << _price << std::endl;
    }
private:
    int _price;// 黄牛挂号价格
    friend class Scalper;  //声明 Scalper 为友元类
};
class Scalper
{
public:
    Hospital h1;
    void Registration()  //黄牛挂号
    {
        h1._price -= 50;  //因Scalper是Hospital的友元类,故此处可以访问其私有成员
        std::cout <<"黄牛挂号价格:" << h1._price << std::endl;
    }
};
int main()
{
    Hospital h1;
    Scalper s1;
    h1.Registration();
    s1.Registration();
    return 0;
}

程序执行结果:

  • 医院挂号价格:100
    黄牛挂号价格:50

第 12 行将 Scalper 声明为 Hospital 的友元类。第 12行使得 Scalper 类的所有成员函数都能访问 Hospital 对象的私有成员。如果没有第 12 行,第 20 行对私有成员 price 的访问就会导致编译错误。
友元类注意事项:

  • 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

  • 友元关系在类之间不能传递。即类 A 是类 B 的友元,类 B 是类 C 的友元,并不能导出类 A 是类 C 的友元。

  • 友元函数没有this指针,则参数要有三种情况:

    • 要访问非static成员时,需要对象做参数;
    • 要访问static成员或全局变量时,则不需要对象做参数;
    • 如果做参数的对象是全局对象,则不需要对象做参数.
  • 友元关系不能被继承。

你可能感兴趣的:(C++,类,封装,编程语言)