c++学习笔记分享--友元

什么是友元?

**友元(friend)**​ 就是让一个类"开个后门",允许别的函数或者别的类访问自己的私有成员(private)和保护成员(protected)。

正常情况下,类的私有成员只有自己内部的成员函数才能访问,外部函数和其他类都不行。但有时候,我们确实需要让某个外部函数或另一个类来访问这些私有数据,这时候就用友元。

友元的两种形式

1. 友元函数

把一个普通函数声明为某个类的友元,这个函数就能访问该类的私有成员。

cpp 复制代码
#include <iostream>
using namespace std;

class Box {
private:
    double width;
public:
    Box(double w) : width(w) {}
    
    // 声明友元函数
    friend void printWidth(Box b);
};

// 友元函数的定义
void printWidth(Box b) {
    // 可以直接访问私有成员 width
    cout << "宽度 = " << b.width << endl;
}

int main() {
    Box box(10.5);
    printWidth(box);  // 输出:宽度 = 10.5
    return 0;
}

2. 友元类

把一个类声明为另一个类的友元,那么这个类的所有成员函数都能访问对方的私有成员。

cpp 复制代码
class A {
private:
    int secret;
public:
    A(int s) : secret(s) {}
    friend class B;  // 声明B是A的友元类
};

class B {
public:
    void showSecret(A a) {
        // B可以访问A的私有成员
        cout << "秘密数字: " << a.secret << endl;
    }
};

重要注意事项

  1. 友元关系不能传递

    A是B的友元,B是C的友元,不代表A是C的友元。就像你朋友的朋友不一定是你的朋友。

cpp 复制代码
#include <iostream>
using namespace std;

class C;  // 前置声明

class A {
private:
    int secretA;
public:
    A(int s) : secretA(s) {}
    friend class B;  // A把B设为友元
    void showC(C c);  // 后面再实现
};

class B {
private:
    int secretB;
public:
    B(int s) : secretB(s) {}
    friend class C;  // B把C设为友元
    
    void showA(A a) {
        // ✅ B是A的友元,可以访问A的私有成员
        cout << "A的秘密: " << a.secretA << endl;
    }
};

class C {
private:
    int secretC;
public:
    C(int s) : secretC(s) {}
    
    void showB(B b) {
        // ✅ C是B的友元,可以访问B的私有成员
        cout << "B的秘密: " << b.secretB << endl;
    }
    
    void showA(A a) {
        // ❌ 编译错误!C不是A的友元,不能访问A的私有成员
        // cout << "A的秘密: " << a.secretA << endl;
        cout << "C不能访问A的私有成员!" << endl;
    }
};

// 现在来实现A::showC
void A::showC(C c) {
    // ❌ A也不是C的友元,不能访问C的私有成员
    // cout << "C的秘密: " << c.secretC << endl;
    cout << "A也不能访问C的私有成员!" << endl;
}

int main() {
    A a(100);
    B b(200);
    C c(300);
    
    b.showA(a);  // ✅ 输出:A的秘密: 100
    c.showB(b);  // ✅ 输出:B的秘密: 200
    c.showA(a);  // ❌ 编译报错
    a.showC(c);  // ❌ 编译报错
    
    return 0;
}

2.友元关系是单向的

A把B设为友元,但B并没有把A设为友元,所以A不能访问B的私有成员。

cpp 复制代码
#include <iostream>
using namespace std;

class B;  // 前置声明

class A {
private:
    int moneyA;
public:
    A(int m) : moneyA(m) {}
    
    friend class B;  // ✅ A说:B是我的好朋友,可以看我的钱
    
    void showBmoney(B b);  // 声明,后面实现
};

class B {
private:
    int moneyB;
public:
    B(int m) : moneyB(m) {}
    
    // ⚠️ 注意:B没有把A设为友元!
    // 没有这行:friend class A;
    
    void showAmoney(A a) {
        // ✅ B是A的友元,可以访问A的私有成员
        cout << "B看到了A的钱: " << a.moneyA << "元" << endl;
    }
};

// 在类外实现A的成员函数
void A::showBmoney(B b) {
    // ❌ A不是B的友元,不能访问B的私有成员
    // cout << "A想看B的钱: " << b.moneyB << "元" << endl;
    cout << "A看不到B的钱,因为B没把A当朋友!" << endl;
}

int main() {
    A a(1000);
    B b(500);
    
    b.showAmoney(a);  // ✅ 输出:B看到了A的钱: 1000元
    a.showBmoney(b);  // ❌ 编译错误
    
    return 0;
}

3.友元不是类的成员

它只是一个"特权通行证",不属于类本身。

4.友元会破坏封装性

能用成员函数解决的问题尽量不用友元,只在确实需要时才使用

什么时候用友元?

  • 运算符重载时经常用到(比如 <<输出运算符)

  • 两个类需要紧密合作时

  • 某些性能敏感场景,避免频繁调用公有接口

有帮助的话留下小小的赞感谢!