结构体成员全为public时,重载<<运算符为何仍需friend关键字?
为什么public成员的结构体重载std::ostream<<仍需要friend关键字?
核心原因和成员函数的运算符重载规则有关,和成员是否public没关系:
- 类/结构体的成员函数重载运算符时,第一个参数默认是当前类的对象(隐式的
this指针)。如果把operator<<写成Vector的成员函数,那它的调用形式只能是vec << cout,这和我们常用的cout << vec完全颠倒,根本不符合使用习惯。 - 你给出的错误写法里,那个成员函数声明了两个参数,但编译器会自动给它加上
Vector* const this的隐式参数,相当于函数有三个参数,这和<<运算符需要两个操作数的规则直接冲突,编译肯定报错。
那friend关键字在这里起什么作用?
它不是为了访问private成员(毕竟你的结构体成员都是public),而是把operator<<定义成全局函数,同时允许它直接访问结构体成员。作为全局函数,它的第一个参数是std::ostream&,第二个是const Vector&,刚好匹配cout << vec的调用逻辑:左操作数是ostream对象,右操作数是Vector对象。
举个直观的调用对比:
- 全局版本(friend定义的):
std::cout << myVec; // 等价于 operator<<(std::cout, myVec); - 错误的成员函数版本:
myVec << std::cout; // 等价于 myVec.operator<<(std::cout);
显然第二种写法完全不是我们想要的。
当然,你也可以不使用friend,直接在结构体外面定义全局的operator<<函数,因为成员都是public,直接访问v.x和v.y没问题。但用friend把它声明在结构体内部,是更规范的写法,能让读者一眼看出这个运算符是和Vector类相关的。
内容的提问来源于stack exchange,提问作者Vladimir Kitanov
相关产品推荐
相关产品推荐

