如何在继承std::stringstream时重载operator<<(double const&)?
自定义stringstream实现double类型特殊格式输出
我需要重载operator<<,让以下代码:
double d = 3.0; mycustomstringstream << "Hello World " << d << "what a nice day."; std::cout << mycustomstringstream.str() << std::endl;
输出结果为:
Hello World (double)(3.00000000000)what a nice day.
要求:
- 使用该自定义流时,所有double类型必须以
(double)(<数值>)的格式输出 - 自定义流需具备
std::stringstream的全部功能,且不愿完全重新实现流 - 目的是避免每次输出double都手动调用转换函数,减少重复操作和错误
我的尝试
全局重载
直接实现全局重载:
std::ostream& operator<<(std::ostream& o, double const& d){ o<<"(double)("<< d << ")"; return o; }
编译报错,提示存在歧义(该运算符已在标准库中定义)。
继承重载
尝试继承std::stringstream并为自定义流重载运算符:
#include <sstream> class MyCustomStringStream: public std::stringstream{}; MyCustomStringStream& operator<<(MyCustomStringStream& o, double const& d){ o<<"(double)("<< ( (std::stringstream)(o) << d ) << ")"; return o; }
出现错误:
error: use of deleted function 'std::__cxx11::basic_stringstream<_CharT, _Traits, _Alloc>::basic_stringstream(const std::__cxx11::basic_stringstream<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
之后修改为:
#include <iostream> #include <sstream> class MyStringStream: public std::stringstream{ std::stringstream aux; public: MyStringStream& operator<<(double const& d){ aux.str() = ""; aux << std::scientific << "(double)(" << d << ")"; *this << aux.str(); return *this; } }; int main() { double d = 12.3; MyStringStream s; s << "Hello World " << d << "what a nice day."; std::cout << s.str() << std::endl; }
但输出结果仍为:
Hello World 12.3what a nice day.
解决方案
问题核心:当调用s << d时,编译器会优先匹配标准库中std::ostream& operator<<(std::ostream&, double)的重载,而非你自定义的成员函数——因为std::stringstream继承自std::ostream,链式调用会触发标准版本。
以下是简洁且符合要求的实现方式:
最终代码
#include <iostream> #include <sstream> #include <iomanip> class MyCustomStringStream : public std::stringstream { public: // 优先匹配double类型的重载 MyCustomStringStream& operator<<(double d) { // 调用基类的operator<<,确保格式符合要求 *static_cast<std::stringstream*>(this) << "(double)(" << std::fixed << std::setprecision(11) << d << ")"; return *this; } // 模板重载处理所有其他类型,转发给基类,保留stringstream全部功能 template<typename T> MyCustomStringStream& operator<<(const T& val) { *static_cast<std::stringstream*>(this) << val; return *this; } }; int main() { double d = 3.0; MyCustomStringStream mycustomstringstream; mycustomstringstream << "Hello World " << d << "what a nice day."; std::cout << mycustomstringstream.str() << std::endl; return 0; }
代码说明
- 优先级匹配:自定义的
operator<<(double)是更具体的重载,会被编译器优先选择,避免触发标准库版本 - 完整功能保留:模板化的
operator<<处理所有非double类型,直接转发给基类std::stringstream,确保自定义流具备原类的全部功能 - 格式控制:使用
std::fixed和std::setprecision(11)保证输出的小数位数与示例一致 - 避免递归:通过
static_cast<std::stringstream*>(this)明确调用基类的输出运算符,防止递归调用自身
输出结果
Hello World (double)(3.00000000000)what a nice day.
内容的提问来源于stack exchange,提问作者GRamon
相关产品推荐
相关产品推荐

