周末,我遇到了功能超载分辨率的具体问题,我似乎无法解决。 下面的代码是对问题的精炼:
#include <iostream>
using namespace std;
template<typename T>
void f(const T& t)
{
cout << "In template function." << endl;
}
class C
{
public:
void f() { cout << "In class function." << endl; }
void g() { int i=0; f(i); }
void h() { int i=0; f<int>(i); }
void i() { extern void f(int); int i=0; f(i); }
};
int main()
{
cout << "Test" << endl;
C c;
c.i();
return 0;
}
1)C :: g将无法编译,因为编译器不会尝试模板。它只是抱怨没有C :: f匹配。
2)C :: h不会无缘无故地编译,这对我来说是显而易见的。消息是“期望在'int'之前的primary-expression”
3)C :: i将编译,但(在评论g和h之后)它将不会链接到任何东西。我想我理解这一点:extern强迫链接器查看另一个编译单元,但任何模板定义都在这个编译单元中。
我很感激有关1和2的原因的任何澄清。另外,最终,有人可以建议一种方法来实现这一点,而不涉及创建另一个编译单元吗?
答案 0 :(得分:3)
可能会找到C::f
而不是全局f
。使用::f<int>(i)
。
答案 1 :(得分:2)
输出:
测试
在模板功能。
#include <iostream>
using namespace std;
template<typename T>
void f(const T& t)
{
cout << "In template function." << endl;
}
class C
{
public:
void f() { cout << "In class function." << endl; }
void g() { using ::f; int i=0; f(i); }
};
int main()
{
cout << "Test" << endl;
C c;
c.g();
return 0;
}
答案 2 :(得分:0)
具有相同名称的函数在具有不同范围的情况下将隐藏具有相同名称的其他函数,即使它们具有不同的签名。
不是使用第一个f的模板,你可以只做f(int)
,结果对#1来说是相同的(C :: f()隐藏了:: f(int))。
一种解决方案是在名称前添加“::”以强制使用全局命名空间。 另一种解决方案是更改名称。
答案 3 :(得分:0)
较小范围内的名称会隐藏外部范围内的名称。
使用::f
表示全局命名空间。
在i()
中,您声明了一个名为f
的函数,但实际上没有定义(它与模板不同),因此您会收到链接器错误。
答案 4 :(得分:0)
在尝试查找函数时,C ++有点“贪婪”。一旦在当前作用域中找到匹配的函数 name (在本例中为class C
),它就会停止然后尝试匹配参数。如果参数不匹配,则不会尝试其他范围。我认为这是为了让编译器编写者保持理智。这就是g
无法编译的原因。
同样的事情适用于h
。它在类范围内看到非模板函数f
并且会混淆。它认为您正在尝试与<
函数进行C::f
比较。
在这两种情况下,您都可以使用::f
将名称限定为全局范围。