题目

编写程序,演示 friend(友元)机制。设计银行账户类 BankAccount 将余额等核心成员声明为 private;分别演示:①将全局函数 auditAccount 声明为友元函数,使其能够合法直接穿透访问私有账户流水;②将审计机构类 BankAuditor 声明为友元类,使其内部所有成员方法均获得对账户私有成员的访问权限。阐明友元关系的单向性、非传递性与非继承性。

输入格式:无需外部输入。

输出格式:输出友元函数与友元类对私有成员审计调用的结果。

数据范围与约定:封装性与受控特权、友元语法与安全边界。

思路与算法

1. 友元打破封装的受控妥协
面向对象强调信息隐藏,但某些外部强关联组件(如流输出重载 operator<<、单元测试驱动、审计类)需要高效直取私有变量。friend 是由类自身内部主动赋予外部的“特权声明”。

2. 友元三大铁律
①单向性:A 是 B 的友元,并不意味着 B 是 A 的友元;②非传递性:A 是 B 的友元,B 是 C 的友元,A 并不自动成为 C 的友元;③非继承性:基类的友元不会被派生类自动继承。

3. 前置声明(Forward Declaration)
当两个类互为友元或互相关联时,必须使用前置声明 class BankAccount; 告知编译器该类型的存在。

完整程序

#include <iostream>
#include <string>

class BankAccount; // 前置声明

// 友元类:专职审计员
class BankAuditor {
public:
    void conductDeepAudit(const BankAccount& acc);
};

class BankAccount {
private:
    std::string owner_;
    double balance_;
    std::string secretKey_;

public:
    BankAccount(std::string owner, double balance, std::string key)
        : owner_(std::move(owner)), balance_(balance), secretKey_(std::move(key)) {}

    // 1. 声明友元全局函数
    friend void quickInspect(const BankAccount& acc);

    // 2. 声明友元类:BankAuditor 内所有方法均可直接访问 private
    friend class BankAuditor;
};

// 友元全局函数实现:直接穿透 private
void quickInspect(const BankAccount& acc) {
    std::cout << "[友元全局函数 quickInspect] 用户: " << acc.owner_ 
              << ", 账面余额: ¥" << acc.balance_ << "\n";
}

// 友元类方法实现:直接穿透 private
void BankAuditor::conductDeepAudit(const BankAccount& acc) {
    std::cout << "[友元类 BankAuditor 深度审计] 户主: " << acc.owner_ 
              << ", 存款: ¥" << acc.balance_ 
              << ", 核心密钥校验: " << acc.secretKey_ << "\n";
}

int main() {
    BankAccount account("张三", 888888.50, "SEC_KEY_9981");

    std::cout << "--- 1. 调用友元全局函数 ---\n";
    quickInspect(account);

    std::cout << "\n--- 2. 调用友元类方法 ---\n";
    BankAuditor auditor;
    auditor.conductDeepAudit(account);

    return 0;
}

运行示例

输出:

--- 1. 调用友元全局函数 ---
[友元全局函数 quickInspect] 用户: 张三, 账面余额: ¥888888.5

--- 2. 调用友元类方法 ---
[友元类 BankAuditor 深度审计] 户主: 张三, 存款: ¥888888.5, 核心密钥校验: SEC_KEY_9981