为什么第一个代码段工作正常,但第二个会导致一个模糊的调用错误?为什么编译器在第二种情况下不能解决函数重载?
摘录1:
int main() {
int x = 1234;
std::cout << x;
}
摘录2:
int main() {
int x = 1234;
operator<<(std::cout, x);
}
编译错误
&#34;运算符&lt;&lt;&##;匹配参数列表
std :: operator&lt;&lt;&#39;:对重载函数的模糊调用
答案 0 :(得分:4)
您正在尝试调用成员函数(std::cout
),就像它是一个自由函数一样:http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
歧义可能来自多重匹配,这些匹配都涉及某种转换,其中没有一种是优选的。编译器错误可能会给你一些可怕的不可读的可能匹配列表,所有这些似乎都无关紧要?
对于运营商,将其称为运营商,而不是功能!将运算符定义为成员是有充分理由的,并且有充分的理由将它们定义为自由函数。您不应该关心在任何特定情况下使用哪种。
如果我想创建支持+
的我自己的类型,我可能有很好的技术理由选择一种方法而不是另一种方法,甚至在未来版本的库中改变主意。你应该关心我选择哪个吗?
请注意operator<<
是内置类型的成员函数(即int
s的各种风格),但对于其他类型是非成员函数,例如{{3} }或char const*
。
答案 1 :(得分:3)
因为整数没有全局(或非成员)operator<<
overloaded function。它是a member of the output stream:
std::cout.operator<<(x);
一个好的编译器应该向你展示一个模糊调用的可能替代方案,它应该告诉你这个。
答案 2 :(得分:1)
运算符是非静态成员函数,因此您可以使用 来自:how to call an operator as function in C++
#include <iostream>
int main() {
int x = 1234;
std::cout.operator<<(x);
}
答案 3 :(得分:0)
来自here:
x
如果重载决策无法选择与此类不同功能相比唯一更好的调用匹配,则调用将不明确。对于char
(int),signed char
版本和#include <iostream>
void foo(char a)
{
}
void foo(signed char b)
{
}
int main() {
foo(1);
}
版本都适合,因此它将是不明确的。还有一个例子:
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& const char* s );
prog.cc:在函数&#39; int main()&#39;: prog.cc:11:10:错误:调用重载&#39; foo(int)&#39;很暧昧 FOO(1);
但是这段代码运行良好的运算符&lt;&lt;(std :: cout,&#34; hello&#34;);
因为
operator<<(std::cout, "hello");
是const char* z = "char*"; // OK
const signed char* x = "signed char*"; // invalid conversion from ‘const char*’ to ‘const signed char*’
const unsigned char y = "unsigned char*"; // invalid conversion from ‘const char*’ to ‘unsigned char’
的唯一选择。还有一个例子:
<DataGrid
IsReadOnly="False"
ItemsSource="{Binding Path=Items, Mode=OneWay}">
<DataGrid.Columns>
<DataGridTemplateColumn
Header="Test"
IsReadOnly="False"
Width="70">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock
VerticalAlignment="Center"
TextAlignment="Left"
Text="{Binding Path=Id, Mode=OneWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox
Name="cmbTest"
DisplayMemberPath=""
HorizontalAlignment="Stretch"
IsEditable="True"
IsEnabled="True"
IsReadOnly="False"
IsSynchronizedWithCurrentItem="False"
ItemsSource="{Binding Path=Items2, Mode=OneWay}"
Margin="0"
SelectedItem="{x:Null}"
SelectedValue="{x:Null}"
SelectedValuePath=""
Text=""
VerticalAlignment="Center"
Visibility="Visible"
SelectionChanged="cmbTest_SelectionChanged">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>