C++类数据写入std::wostringstream报错,求重载及输出方案
咱们先拆解你遇到的E0349和C2679错误的核心原因:你为类A重载的operator<<是绑定到std::wostringstream这个特定流类的,但C++的流操作是基于基类多态设计的——所有宽字符输出流(比如wostringstream、wcout)都继承自std::wostream。当你在类B的重载里尝试输出source.ArrayOfA[i]时,编译器找不到适配std::wostream的operator<<(毕竟你只写了wostringstream版本),自然会报错。而且直接重载特定流类也不符合规范,这样你的类A只能在wostringstream里用,没法适配其他宽字符流。
接下来一步步解决问题:
第一步:修正类A的运算符重载
把类A的operator<<改成基于std::wostream的通用版本,这样所有宽字符流都能输出A对象:
先修改A的类声明:
class A { public: A(); ~A(); inline A(float _x, float _y, float _z) : x(_x), y(_y), z(_z) { } inline void Set(float _x, float _y, float _z); float x, y, z; friend std::ostream& operator<<(std::ostream& out, const A& source); friend std::wostream& operator<<(std::wostream& out, const A& source); // 替换成wostream基类 private: };
然后实现这个重载(注意要用宽字符字面量L'',避免窄转宽的编码问题):
std::wostream& operator<<(std::wostream& out, const A& source) { out << L'<' << source.x << L',' << source.y << L',' << source.z << L'>'; return out; }
第二步:修正类B的运算符重载
同样,类B的operator<<也要改成基于std::wostream的版本,保证通用性:
修改B的类声明:
class B { public: A* ArrayOfA; bool Initialize(const A* samples, unsigned int count); friend std::wostream& operator<<(std::wostream& out, const B& source); // 替换成wostream基类 B(); ~B(); private: };
实现类B的重载(这里提个小建议:你写的固定i<4不太灵活,最好给B加个成员变量存储数组实际长度,比如unsigned int arrayCount,这样循环更安全):
std::wostream& operator<<(std::wostream& out, const B& source) { for (unsigned int i = 0; i < 4; ++i) { out << L":" << source.ArrayOfA[i] << std::endl; // 现在能正确匹配A的wostream版本运算符了 } return out; }
改完之后,你原来的代码std::wostringstream wss; wss << ClassB;就能正常运行了——因为wostringstream是wostream的派生类,会自动匹配基类版本的运算符。
关于你问的:若仅用std::ostream,如何获取宽字符串?
如果你只能用窄字符的std::ostream,想要得到宽字符串可以这么做:
先用std::ostringstream生成窄字符串,再通过编码转换转成宽字符串:
#include <locale> #include <codecvt> #include <string> // 先输出到窄字符流 std::ostringstream oss; oss << ClassB; std::string narrow_str = oss.str(); // 转换为宽字符串(UTF-8转宽字符) std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; std::wstring wide_str = converter.from_bytes(narrow_str);
不过更推荐的还是直接用宽字符流方案——毕竟这是C++处理宽字符输出的标准方式,能避免编码转换的潜在问题。
最后总结你的重载问题
你之前的重载错误在于绑定了特定的流类而非通用基类,违背了C++流的多态设计原则。换成基类std::wostream的重载后,不仅解决了当前的编译错误,还让你的自定义类能适配更多输出场景(比如直接输出到std::wcout)。
内容的提问来源于stack exchange,提问作者pivnothebearrrrrrrrr

