为什么重载的operator<<无法访问Box类的私有成员
错误原因
C++类的私有成员遵循严格的访问控制规则:私有成员仅允许类自身的成员函数、以及类显式声明的友元函数/友元类访问。
你实现的ostream& operator<<(ostream& out, const Box& B)是全局作用域的独立函数,既不属于Box类的成员,也没有被Box声明为友元,因此直接访问Box实例的私有成员l、b、h时,会被编译器判定为权限非法。
另外原代码的operator<<实现还有一个逻辑问题:函数接收了输出流参数out,但内部却用cout输出,会导致向非标准输出流(比如文件流、字符串流)写入时逻辑错误。
修复方案
方案1:将流操作符声明为Box类的友元(推荐)
这是C++中重载流输出操作符的标准写法,只需要在Box类的公有区域添加友元声明,授予该全局函数私有成员访问权限即可,修正后的完整代码如下:
#include<bits/stdc++.h> using namespace std; class Box{ int l, b, h; public: Box(): l(0), b(0), h(0) {} Box(int length, int breadth, int height): l(length), b(breadth), h(height) {} bool operator<(const Box& B) const { // 补充const修饰,支持const实例调用 if (l < B.l) return true; if (b < B.b && l == B.l) return true; if (h < B.h && b == B.b && l == B.l) return true; return false; } // 友元声明,授予流操作符私有成员访问权限 friend ostream& operator<<(ostream& out, const Box& B); }; ostream& operator<<(ostream& out, const Box& B){ out << B.l << " " << B.b << " " << B.h; // 替换为传入的out流,适配所有输出流场景 return out; }
方案2:添加公有成员访问器
如果不希望使用友元,可以为三个私有成员添加公有的只读get方法,流操作符通过公有方法获取成员值,无需直接访问私有成员:
class Box{ int l, b, h; public: Box(): l(0), b(0), h(0) {} Box(int length, int breadth, int height): l(length), b(breadth), h(height) {} bool operator<(const Box& B) const { if (l < B.l) return true; if (b < B.b && l == B.l) return true; if (h < B.h && b == B.b && l == B.l) return true; return false; } // 公有只读访问接口 int getLength() const { return l; } int getBreadth() const { return b; } int getHeight() const { return h; } }; ostream& operator<<(ostream& out, const Box& B){ out << B.getLength() << " " << B.getBreadth() << " " << B.getHeight(); return out; }
注:原代码中
operator<的入参和函数本身都没有加const修饰,会导致传入const Box实例、或者对const Box容器排序时出现编译错误,上述代码已经同步修正该问题。
内容的提问来源于stack exchange,提问作者suraj patil
相关产品推荐
相关产品推荐

