• 友元利弊:
    友元不是类的成员但能访问类中的私有成员。友元的作用在于提高程序的运行效率,但也破坏了类的封装。

  • 注意事项:
    (1)友元关系不能被继承;
    (2)友元关系是单向的,不具有交换性;
    (3)友元关系不具有传递性;

一、友元函数

  • 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员
  • 尽管友元函数的原型有在类的定义中出现过,但是 友元函数并不是成员函数
  • this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象
  • 友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针

1. 友元函数是全局函数

class A
{
    friend void printA(const A &a);
public:
    void printA();

private:
    string name {"C++"};
    int id {1024};
    
};
void A::printA(){
    cout << "name = " << this->name << "\t id = " << this->id << endl;
}
// 请注意:printA() 不是任何类的成员函数
void printA(const A &a){
    cout << "name = " << a.name << "\t id = " << a.id << endl;
}
int main()
{
    A a;
    printA(a);
    a.printA();
    return 0;
}

输出:

Start
name = C++	 id = 1024
name = C++	 id = 1024
0
Finish

2. 友元函数是类的成员方法

小技巧:为了防止相互嵌套,可以将其中一个类的声明和实现拆开

class Point;

class PointManager{
public:
    double getDistance(Point &p1, Point &p2);
private:
};
class Point{
    friend double PointManager::getDistance(Point &p1, Point &p2);
public:
    Point(int x, int y){
        this->x = x;
        this->y = y;
    }
private:
    int x;
    int y;
};
double PointManager::getDistance(Point &p1, Point &p2){
    int dx = p1.x - p2.x;
    int dy = p1.y - p2.y;
    return sqrt(dx * dx + dy * dy);
}
int main( )
{ 
    Point p1(1, 1), p2(3, 1);
    PointManager pm;
    cout << pm.getDistance(p1, p2) << endl;
    return 0;
}

输出:

Start
2
0
Finish

二、友元类

class A{
    friend class B;     // 将 B 声明为友元类后,在 B 中 A 就是透明的
public:
    A(int a){
        this->a = a;
    }
    void printA(){
        cout << "a = " << this->a << endl;
    }
private:
    int a;
};
class B{
public:
    B(int b){
        this->b = b;
    }
    void printB(){
        A a(10);
        cout << "print a in b: " << a.a << endl;
        cout << "b = " << this->b << endl;
    }
private:
    int b;
};
int main( )
{ 
    B b(-10);
    b.printB();
    return 0;
}
Start
print a in b: 10
b = -10
0
Finish