C++友元函数与友元类
友元机制允许特定的函数或类访问另一个类的私有和保护成员。虽然友元打破了封装性,但在某些场景下可以提供更清晰的接口设计。
友元函数可以访问类的私有成员,常用于运算符重载。
#include
#include
class Vector2D {
double x_, y_;
public:
Vector2D(double x = 0, double y = 0) : x_(x), y_(y) {}
friend Vector2D operator+(const Vector2D& a, const Vector2D& b);
friend Vector2D operator*(const Vector2D& v, double scalar);
friend double dot(const Vector2D& a, const Vector2D& b);
friend std::ostream& operator<<(std::ostream& os, const Vector2D& v);
double magnitude() const {
return std::sqrt(x_ * x_ + y_ * y_);
}
};
Vector2D operator+(const Vector2D& a, const Vector2D& b) {
return Vector2D(a.x_ + b.x_, a.y_ + b.y_);
}
Vector2D operator*(const Vector2D& v, double scalar) {
return Vector2D(v.x_ * scalar, v.y_ * scalar);
}
double dot(const Vector2D& a, const Vector2D& b) {
return a.x_ * b.x_ + a.y_ * b.y_;
}
std::ostream& operator<<(std::ostream& os, const Vector2D& v) {
os << "(" << v.x_ << ", " << v.y_ << ")";
return os;
}
void friend_function_example() {
Vector2D v1(3, 4);
Vector2D v2(1, 2);
Vector2D sum = v1 + v2;
Vector2D scaled = v1 * 2.0;
double product = dot(v1, v2);
std::cout << "v1: " << v1 << "\n";
std::cout << "v2: " << v2 << "\n";
std::cout << "sum: " << sum << "\n";
std::cout << "scaled: " << scaled << "\n";
std::cout << "dot product: " << product << "\n";
}
友元类可以访问另一个类的所有私有成员。
class Engine {
int rpm_;
double temperature_;
friend class Car;
public:
Engine() : rpm_(0), temperature_(20.0) {}
private:
void start() {
rpm_ = 1000;
temperature_ = 90.0;
std::cout << "Engine started\n";
}
void stop() {
rpm_ = 0;
temperature_ = 20.0;
std::cout << "Engine stopped\n";
}
};
class Car {
Engine engine_;
bool running_;
public:
Car() : running_(false) {}
void start() {
if (!running_) {
engine_.start();
running_ = true;
std::cout << "Car started, RPM: " << engine_.rpm_ << "\n";
}
}
void stop() {
if (running_) {
engine_.stop();
running_ = false;
std::cout << "Car stopped\n";
}
}
void display_status() const {
std::cout << "Engine RPM: " << engine_.rpm_
<< ", Temperature: " << engine_.temperature_ << "°C\n";
}
};
void friend_class_example() {
Car car;
car.start();
car.display_status();
car.stop();
}
友元声明可以用于实现特殊的访问控制模式。
class BankAccount {
double balance_;
std::string account_number_;
friend class Bank;
friend class Auditor;
public:
BankAccount(const std::string& number, double initial)
: account_number_(number), balance_(initial) {}
void deposit(double amount) {
if (amount > 0) {
balance_ += amount;
std::cout << "Deposited: " << amount << "\n";
}
}
double get_balance() const {
return balance_;
}
};
class Bank {
public:
void transfer(BankAccount& from, BankAccount& to, double amount) {
if (from.balance_ >= amount) {
from.balance_ -= amount;
to.balance_ += amount;
std::cout << "Transferred " << amount << " from "
<< from.account_number_ << " to " << to.account_number_ << "\n";
} else {
std::cout << "Insufficient funds\n";
}
}
};
class Auditor {
public:
void audit(const BankAccount& account) {
std::cout << "Auditing account " << account.account_number_
<< ", Balance: " << account.balance_ << "\n";
}
};
void access_control_example() {
BankAccount acc1("ACC001", 1000);
BankAccount acc2("ACC002", 500);
Bank bank;
bank.transfer(acc1, acc2, 200);
Auditor auditor;
auditor.audit(acc1);
auditor.audit(acc2);
}
友元函数可以是另一个类的成员函数。
class Display;
class Data {
int value_;
friend void Display::show(const Data& d);
public:
explicit Data(int v) : value_(v) {}
};
class Display {
public:
void show(const Data& d) {
std::cout << "Data value: " << d.value_ << "\n";
}
};
友元关系不是对称的,也不能传递。
class A {
int secret_;
friend class B;
public:
explicit A(int s) : secret_(s) {}
};
class B {
int data_;
public:
explicit B(int d) : data_(d) {}
void access_A(const A& a) {
std::cout << "B accessing A's secret: " << a.secret_ << "\n";
}
};
class C {
public:
void try_access_A(const A& a) {
std::cout << "C cannot access A's secret\n";
}
};
友元机制应该谨慎使用,只在确实需要打破封装时才使用。过度使用友元会降低代码的可维护性。
C++友元函数与友元类
张小明
前端开发工程师
如何使用代理保护电子邮件营销?如何保护您的收件箱
电子邮件仍然是企业和个人最广泛使用的沟通渠道之一,同时也是网络犯罪分子最常攻击的目标之一。从网络钓鱼和垃圾邮件泛滥到凭证窃取和未经授权的账户访问,电子邮件收件箱时刻面临风险。据行业报告显示,电子邮件仍然是超过 90% 网络攻击的主要…
2026年必看:六款热门AI编程工具横评,Trae与Cursor怎么选
2026年必看:六款热门AI编程工具横评,Trae与Cursor怎么选AI编程工具正从辅助插件进化为全流程开发核心,2026年市场进入智能体协作新阶段。本文精选6款主流AI编程工具,从核心功能、协作模式、适配场景等维度深度解析,帮开…
喜讯|VeryCloud睿鸿股份再获亚马逊云科技年度成长之星合作伙伴殊荣
2026年5月21日,VeryCloud睿鸿股份凭借其卓越的技术服务能力与丰硕的客户合作成果,再次荣获亚马逊云科技“年度成长之星合作伙伴(咨询类)”奖项。这是继2022年后,VeryCloud睿鸿股份再次获此殊荣,标志着其作为…
Token聚合平台 vs 传统云 vs AI原生云,AI推理应用怎么选?
在大模型能力深度融入生产环境的当下,后端 AI 架构的选择往往决定了应用的生死。从早期的“调用一个接口”到如今复杂的智能体(Agent)工作流,开发团队在底座选型上面临着两条截然不同的演进路径:一条是追求便利与极致轻…
开源软件的开发与贡献:如何参与开源项目
一、开源项目:软件测试从业者的新赛道在软件行业快速迭代的今天,开源项目早已不再是开发者的专属领地。对于软件测试从业者而言,参与开源项目不仅是提升专业能力的绝佳途径,更是拓展职业边界、积累行业资源的重要方式。开源项目的…
(二) 1. Q-learning的遗憾界分析-高效的Q-learning算法
高效的Q-learning算法 1.1. 无模型算法 1.2. UCB算法 1.3. 文献回顾 无模型(Model-free)强化学习算法(如 Q-learning)无需显式地对环境进行建模,而是直接对价值函数或策略进行参数化和更新。与基于模型(Model-based)的方法相比,这类算法通常更简单、更灵活,因此在现代…