请参见下面的代码
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}
如果TestClass在to_string()
内未实现功能TestClass
,则可以将to_string(m_value)
解析为stringhelper::to_string(int)
。但是,当TestClass实现函数to_string()时,编译器无法将to_string(int)
解析为stringhelper::to_string
。
相反,它坚持/将函数解析为TestClass::to_string
,并给出了错误消息,函数TestClass::to_string
没有接受1个参数。
为什么会这样?
环境:
Visual Studio 2008专业版9.0.21022.8 RTM
配置:Win32
Windows 8
答案 0 :(得分:0)
此行为不仅限于Visual Studio2008。如果在现代Clang实现中进行测试,您将看到相同的行为。如您所知,派生类中的函数不会覆盖基类中的函数,但具有相同的名称,这些函数将在基类中隐藏其他相同名称的函数。
这里的“问题”是您通过使用using
语句将名为to_string
的函数引入了一个范围,该范围本质上是与上述示例完全相同的受害者,当您从班级内部查看时。
如果标准让您使用this->foo()
调用成员函数,则可能不会成为问题。但是,由于假定一个类中的函数调用是该类的一部分,并且只有在未找到其他范围的情况下,这才成为问题。
由于您的课程中有一个实现,因此具有优先级并将被使用。由于您需要一个以int
作为参数的版本,因此将查找成员函数的重载版本,并且由于该版本不存在,您将看到错误。
这是using namespace
经常会引入可能难以理解的错误的原因之一。如果要确保在类名与函数相同的类中使用stringhelper::to_string
实现,则必须明确。
例如,即使您保留using
语句,此方法也可以正常工作。
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + stringhelper::to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}