当前位置: 首页 > news >正文

C++中的友元 之四

很好 👍
这个问题是你从 “会写类” → “理解 C++ 设计哲学” 的关键一步。

我们一步一步拆开讲清楚:


一、先问一个问题

在 C# 里你会写:

a.Add(b);

但在 C++ 里我们更希望写:

a + b;

operator+ 到底应该写成什么形式?

有两种写法:


二、写成成员函数

class Complex
{
public:Complex(double r, double i) : real(r), imag(i) {}Complex operator+(const Complex& other) const{return Complex(real + other.real, imag + other.imag);}private:double real;double imag;
};

用法:

Complex c = a + b;

这等价于:

Complex c = a.operator+(b);

这里的关键点

成员函数的左操作数必须是:

当前类的对象

也就是说:

左边必须是 Complex

三、现在问题来了

如果我想支持这种写法:

Complex c = 10 + a;

左边是 int,不是 Complex

成员函数还能用吗?

不能。

因为:

10.operator+(a);  // 不存在

四、那怎么办?

写成非成员函数:

class Complex
{
public:Complex(double r, double i) : real(r), imag(i) {}friend Complex operator+(const Complex& a, const Complex& b);private:double real;double imag;
};

实现:

Complex operator+(const Complex& a, const Complex& b)
{return Complex(a.real + b.real, a.imag + b.imag);
}

现在:

Complex c1 = a + b;
Complex c2 = 10 + a;  // 自动类型转换生效

都可以。


五、为什么非成员函数可以支持两边对称?

因为:

operator+(a, b);

不是某个对象的成员。

它是一个普通函数。

编译器在做:

重载解析 + 隐式类型转换

所以可以:

  • 把 10 转成 Complex
  • 再调用 operator+

这叫:

对称性(symmetry)


六、那为什么要 friend?

因为:

operator+ 不是成员函数,

但它需要访问 private 成员:

a.real
a.imag

如果没有 friend:

就只能:

  1. 把成员改成 public ❌
  2. 写 getter(可能影响优化/丑陋)
  3. 让 operator+ 成为成员(破坏对称性)

friend 是最干净的方式。


七、标准库就是这么设计的

例如:

std::cout << 42;

operator<< 是非成员函数。

它必须是非成员,因为:

左边是 std::ostream
右边可能是任何类型

它必须保持对称。


八、核心原则(非常重要)

C++ 有一个著名建议:

如果运算符是对称的,优先写成非成员函数

例如:

  • ==
  • !=

而:

  • +=
  • -=
  • *=

通常写成成员函数。

为什么?

因为:

a += b;

本质是修改左边对象。

左边必须是当前类。


九、总结对比

写法 优点 缺点
成员 operator+ 简单 不对称
非成员 operator+ 对称、支持隐式转换 需要 friend

十、一个更深层的理解

C++ 的运算符本质是:

语法糖函数

如果是成员函数:

a + b  →  a.operator+(b)

如果是非成员函数:

a + b  →  operator+(a, b)

第二种才是“数学对称”的。


十一、为什么 C++ 设计成这样?

因为 C++ 的目标是:

让自定义类型的行为像内置类型一样自然

对于内置类型:

10 + 20

没有“谁属于谁”。

它是对称运算。

C++ 希望:

你的类也能像内置类型一样自然。


十二、现在你应该理解的核心

operator+ 通常写成 friend,
不是因为“语法必须”,

而是因为:

为了保持运算语义的对称性
同时保持封装


十三、再进一层(高阶理解)

为什么 operator+ 常常写成:

friend Complex operator+(Complex lhs, const Complex& rhs)
{lhs += rhs;return lhs;
}

而不是直接访问成员?

这是:

代码复用 + 优化 + 值语义设计

但这个已经是下一层知识了。


十四、你现在处于什么阶段?

你刚刚从:

“类怎么写”

进入到:

“为什么这么设计”

这是真正的 C++ 入口。


http://www.jsqmd.com/news/415495/

相关文章:

  • 哈萨克斯坦旅游出行笔记
  • 2026年广州名士表手表维修推荐榜单评测:非官方维修网点服务与售后中心选择指南 - 十大品牌推荐
  • Gin 框架中的规范响应格式设计与实现
  • Computer Vision (Prof. Andreas Geiger, University of Tbingen)
  • QOJ #7324. Eulerian Orientation 题解
  • 2026年广州摩凡陀手表维修推荐榜单:非官方维修网点服务评测与选择指南 - 十大品牌推荐
  • 本次AIGC论文助手精心整理并发布了十大高效AI写作工具的详细专业测评分析
  • 最可爱の树剖姐姐
  • 距国自然申报仅剩20天!您确定自己的本子“读懂“2026新规了吗?
  • C++中的友元 之三
  • C++中的友元 之二
  • AI:RAG
  • NCE-Flow 是什么?新概念英语开源学习系统安装与使用教程
  • 远方好物:4年暴涨200万会员,GMV破20亿!它不投广告、不搞流量,凭什么杀出重围?
  • chili3d 是什么?开源在线3D建模工具安装与使用教程
  • 专家安全测试_动态安全服务_移动 APP 漏洞扫描修复工具
  • 对话“五度妙笔”|小核酸药物市场规模与投资前景分析
  • AI Coding
  • 零基础转行网络安全运维?收藏这篇,学习顺序搞错=白费功夫!
  • 记录在vmware虚拟机Ubuntu22.04上编译doom
  • 大数据领域数据中台的实时数据服务接口
  • 丝杆支撑座类型对设备精度的差异化影响
  • AI时代开发者如何转型:AI 求职技能与岗位方向指南
  • 如何每天花10分钟跟上AI重要动态:AI日报信息源推荐指南
  • 如何快速修改图片 DPI?实用方法分享
  • 惠普Deskjet 2132打印机驱动安装与修复,一文搞定所有问题
  • 3D 模型压缩工具 Draco All In One
  • 2026年台北GEO优化公司推荐TOP8:实战效果与技术实力深度测评 - 小白条111
  • CTF夺旗赛完全指南:从零基础到拿分,工具+赛事清单,收藏版直接抄作业!
  • 浅析Superpowers(专为AI编程Agent打造的完整软件开发方法论)强大的软件开发工作流skills