考虑以下代码:
#include <iostream>
namespace N {
class A {};
void f(A a) { std::cout << "N::f\n"; }
}
void f(int i) { std::cout << "::f\n"; }
template <typename T>
class Base {
public:
void f(T x) { std::cout << "Base::f\n"; }
};
template <typename T>
class X : public Base<T> {
public:
void g() {
T t;
f(t);
}
};
int main()
{
X<N::A> x1;
x1.g();
X<int> x2;
x2.g();
}
该代码旨在研究名称查找在C ++中的工作方式。
如果我用GNU C ++(版本6.1.0)编译这个程序,它会打印:
N::f
::f
但如果我使用Microsoft Visual Studio 2015编译它,它会打印:
Base::f
Base::f
哪种行为正确,为什么?
答案 0 :(得分:15)
g ++符合标准,而Visual C ++不符合:
14.6.2从属名称[temp.dep]
3在类或类模板的定义中,的范围 在不合格的情况下,不检查依赖基类(14.6.2.1) 名称查找或者在类模板的定义点或 成员或在类模板或成员的实例化期间。
用f()
替换this->f()
将找到基本成员。
答案 1 :(得分:6)
在函数String fragment = getIntent.getStringExtra("fragment");
// Do something to load correct fragment
的函数定义中,名称g
被视为在类外声明的函数(在类定义中,此名称未声明; f是从属名称)。
f
因此编译器使用ADL查找。
但是,如果要编写成员函数的显式调用
template <typename T>
class X : public Base<T> {
public:
void g() {
T t;
f(t);
}
};
然后函数class X : public Base<T> {
public:
void g() {
T t;
this->f(t);
}
};
的调用将被视为对基类的成员函数的调用。
因此,似乎MS VC ++ 2015有一个错误。