重载运算符<< (无符号字符类型定义为字节)
我想重载(劫持?)ostream
和 basic_ostream
以便它停止尝试将八位字节(无符号字符)显示为可打印字符。
我已经和 cout
以及朋友们在屏幕上放笑脸一起生活了太久了。我厌倦了使用强制转换:hex << int(0xFF & b) << ...
。
是否可以覆盖标准行为?我已经尝试过模板和非模板覆盖。它们编译,但似乎没有被调用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
问题是
命名空间 std 中已经存在一个。由于
basic_ostream<>
也在该命名空间中,因此当您输出unsigned char
时,ADL 会选取它。添加您自己的重载可能会使调用运算符变得不明确,或者您的重载将被默默地忽略。但即使它能工作,它也会很脆弱,因为忘记一个包含可能会巧妙地改变代码的含义,而无需编译器进行任何诊断。
还有更多:每个查看此类代码的维护程序员都会假设调用了标准运算符(并且在向代码添加另一个输出语句时永远不会想到添加包含)。
简而言之,最好添加一个函数来完成您想做的事情。
一个合理的语义替代方案可能是添加一个流操纵器来调用您想要的输出格式。不过,我不确定这在技术上是否可行。
The problem is that there already is a
in
namespace std
. Sincebasic_ostream<>
is also in this namespace, ADL picks it up when you output anunsigned char
. Adding your own overload might make calling the operator ambiguous, or your overload will silently be ignored.But even if it would work, it would be brittle, because forgetting one include might subtly alter the meaning of the code without any diagnostic from the compiler.
And there's more: Every maintenance programmer looking at such code will assume the standard operator is called (and never think of adding an include when he adds another output statement to the code).
In short, it might be best to add a function doing what you want to do.
A reasonable semantic alternative to that might be to add a stream manipulator that invokes the output format you want. I'm not sure if that's technically possible, though.
吕克是对的。
如果您不介意十进制输出,则当前方法的更快替代方案是将 char 提升为 int:
我不明白这会带来多大的负担!
Luc is correct.
A quicker alternative to your current approach — if you don't mind decimal output — is to promote the char to
int
:I don't see how this would be taxing!
这与 MSVC 10.0 和 MinGW g++ 4.4.1 配合得很好,并且可以用 Comeau Online 干净地编译,所以我相信它在形式上没问题。
干杯&呵呵,
This works nicely with MSVC 10.0 and MinGW g++ 4.4.1, and it compiles cleanly with Comeau Online, so I believe it's formally OK.
Cheers & hth.,
阿尔斯是对的,你所要求的事情不会发生。
你能做的最好的事情就是编写你自己的IO操纵器(
iomanip
)来为你施展魔法。在这种情况下,你需要一个接受unsigned char
的函数(尽管我强烈建议使用
中的uint8_t
)。然后你可以这样写:
你可以向
asHex
添加构造函数,甚至使其成为一个模板类来支持 16、32 和其他位数。(是的,我知道
不是官方的 C++ 头文件,但我宁愿将其定义放在全局命名空间中,而不是std::
中必须执行using namespace std;
转储全局命名空间中的所有内容。)Als is right that what you're asking for isn't going to happen.
The best you can do is to write your own IO manipulator (
iomanip
) to do the magic for you. In this case, you need a function that takes anunsigned char
(though I'd strongly recommend usinguint8_t
from<stdint.h>
).Then you can write:
You can add constructors to
asHex
or even make it a template class to support 16, 32, and other bit counts.(Yes, I know
<stdint.h>
is not an official C++ header, but I'd rather have its definitions in the global namespace instead ofstd::
without having to do ausing namespace std;
which dumps everything in the global namespace.)由于 ADL,将调用标准
operator<<
。尝试明确限定您的调用:Due to ADL the standard
operator<<
will be called. Try to explicitly qualify your call:您无法直接覆盖
std::cout
的行为。如果任何开发代码可以更改其他代码使用的标准库的行为,那就太容易出错了。您可以创建自己的类来模拟
std::cout
的行为并使用该对象。You cannot override the behavior of
std::cout
directly. It would be too error-prone if any dev code can change the behavior of the standard library used by other code.You can create your own class that emulates the behavior of
std::cout
and use that object instead.