【发布时间】:2014-05-02 18:57:48
【问题描述】:
在回答之前:这不是关于如何让这段代码做我想做的事情的问题。我已经知道该怎么做(见这个问题的结尾)。这是一个关于理解编译器为什么会这样做的问题。
请考虑以下(简化的)代码:
#include <iostream>
void operator>>( std::istream &stream, char chr )
{
std::cout<<"Called "<<chr<<"\n";
}
int main()
{
char c='b';
std::cin>>c;
return 0;
}
使用 gcc 4.8.2 和 -Wall -Wextra 编译会产生一个不相关的警告(未使用流)。但是,运行时会打印“Called b”。
我预计会发生两件事之一。要么程序从标准输入中读取一个字符,要么代码无法编译,因为编译器发现我的运算符和标准库定义的运算符不明确。标准库定义的算子,据我理解,相当于:
std::istream &operator>>( std::istream &stream, char &c )
无论如何,我没想到会调用我的操作员。
更奇怪的是,由于上面提到的歧义,以下代码无法编译:
#include <iostream>
void function(char &chr)
{
std::cout<<"1 "<<chr<<"\n";
}
void function(char chr)
{
std::cout<<"2 "<<chr<<"\n";
}
int main()
{
char c='a';
function(c);
return 0;
}
除了使用函数而不是运算符之外,我认为编译器对这两种情况的决定没有任何区别。
注意:我完全意识到标准库定义的和我上面写的原型并不完全相同。我认为,在解决函数方面,至少在这个用例中,没有什么重要的区别。请记住,std 定义不能有默认参数,因为这是运算符重载。
另外,正如我在问题开头所写的,我已经知道如何让代码做正确的事。用“const char &”而不是“char”定义我的运算符会导致编译器选择正确的重载。
【问题讨论】:
-
嗯,这可能与您的过载采用
istream比stream更具体的事实有关吗?我想我记得在标准中读到,在编译器构建的集合中的重载之间进行选择时,实际上会选择具有最具体参数类型的函数。疯狂的猜测,因为我不确定...... -
你的输入操作符会导致undefined behavior,它应该返回你传入的流。如果你只收到一个警告,你真的应该启用更多警告(至少
-Wall)。跨度> -
至于被调用,记住 C++ 是基于 arguments 而不是返回类型进行重载的。
-
@JoachimPileborg 返回类型为
void -
@JoachimPileborg 但是 OP 不链接该运算符。因此没有编译器错误,也没有由于没有从函数返回任何内容而导致的 UB。