Visual Studio无法解析类和名称空间中的重载明确功能

时间:2018-09-25 03:59:45

标签: c++

请参见下面的代码

#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

1 个答案:

答案 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();
}