1 友元

  • 友元发生在函数和类之间或者类与类之间
  • 友元不是类的一部分
  • 友元不受类中访问级别的限制,可以直接访问具体类的所有成员
  • 友元关系是单向的,不能传递

在类中用 friend 关键字对函数或类进行声明

1.1 函数友元

当一个函数声明为类的友元时,就可以访问类中的所有成员。

编程实验:函数是类的友元

// 18-1.cpp
#include<stdio.h>
#include<math.h>
class Point
{
public:
    Point(int xx, int yy) : x(xx), y(yy){}
    double getX() { return x; }
    double getY() { return y; }
    friend double func(Point& p1, Point& p2);
private:
    double x, y;
};
double func(Point& p1, Point& p2)
{
    double ret = pow(p1.x-p2.x, 2) + pow(p1.y - p2.y, 2);
    ret = sqrt(ret);
    return ret;
}
int main()
{
    Point p1(1, 2);
    Point p2(4, 6);
    printf("p1(%f, %f)\n", p1.getX(), p1.getY());
    printf("p2(%f, %f)\n", p2.getX(), p2.getY());
    printf("%f\n", func(p1, p2));
    return 0;
}

函数 func() 是类的友元,可以访问类中的所有成员,可以直接访问类中的私有成员。

$ g++ 18-1.cpp -o 18-1
$ ./18-1
p1(1.000000, 2.000000)
p2(4.000000, 6.000000)
5.000000

1.2 类友元

当一个类 A 声明为另一个类 B 的友元时,就可以访问类 B 中的成员。

// 18-2.cpp
#include<stdio.h>
class ClassC
{
public:
    ClassC(const char* cc) : c(cc){}
    friend class ClassB;
private:
    const char* c;
};
class ClassB
{
public:
    ClassB(const char* cc) : c(cc){}
    friend class ClassA;
    void getClassCName(ClassC& c)
    {
        printf("c.n = %s\n", c.c);
    }
private:
    const char* c;
};
class ClassA
{
public:
    ClassA(const char* cc) : c(cc){}
    void getClassBName(ClassB& b)
    {
        printf("b.n = %s\n", b.c);
    }
private:
    const char* c;
};
int main()
{
    ClassA A("A");
    ClassB B("B");
    ClassC C("C");
    A.getClassBName(B);
    B.getClassCName(C);
    return 0;
}

上面的代码中:
在类 B 中声明 friend class ClassA; 则 A 是 B 的友元;A可以访问 B 的成员。
在类 C 中声明 friend class ClassB;,则 B 是 C 的友元;B 可以访问 C 中的成员。

友元关系不具有传递行性,A 不是 C 的友元。

$ g++ 18-2.cpp -o 18-2
$ ./18-2
b.n = B
c.n = C

1.3 友元的缺点

友元直接破坏了面向对象的封装性,高效的同时得不偿失,已经逐渐被遗弃。

2 小结

1、类的友元可以是函数,也可以是类
2、友元不具备传递性
3、友元破坏了面向对象的封装性