题目
编写程序,演示 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