5

可能重复:
未解决的重载函数类型 c++

考虑下面的代码片段:

#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
void test(){
    std::string str = "Hello World!";
    std::transform(str.begin(), str.end(), str.begin(), tolower);
}

tolower使用 G++ 编译时出现错误:未解析的重载函数

如果using namespace std;被删除,代码工作正常。

然后,我的问题是:

  • namespace std与C函数有什么关系?
  • #include<ctype.h>和 和有什么不一样#include<cctype>?尽管它们在上面的示例中都不起作用。
  • 为什么std::tolower也不起作用?std::tolower和有什么区别tolower
4

2 回答 2

5

您可以使用命名空间运算符来使用 C 版本,tolower如下所示:

::tolower(); // nothing before '::' means look in the global namespaece.

这将强制编译器查找不在特定命名空间内的函数,所有基于 C 的 API 都是这种情况。

至于为什么std::tolower不起作用,我不知道。cpp 参考的例子没有使用std::transform,这可能是原因。

于 2012-07-16T06:23:05.387 回答
5

namespace std和 C 函数之间没有关系。但是您的代码不是 C,而是 C++,因此您还必须考虑 C++ 函数。例如std::tolower,在 中<locale>。你的问题是由于事情的一致:

  • 您包含的标题之一包括<locale>. C++ 头文件允许包含其他 C++ 头文件,并且哪个头文件包含哪个其他头文件可能因一种实现而异,因此您编写的代码可能使用一种编译器编译,而不是另一种编译器。

  • 您试图将函数作为指向函数参数的指针传递给参数是模板类型参数的函数模板。简单来说,这里为了做重载解析 tolower,编译器必须将其与参数的类型相匹配,而为了知道参数的类型,编译器必须根据函数的确切类型进行模板类型推导,它只有在完成重载解析后才能知道。

如果你想要这个函数<ctype.h>(你不想要,因为它会导致未定义的行为),你可以通过 include <ctype.h>(保证它存在于全局命名空间中)和 using::tolower或通过显式指定重载来获得它你想要,例如static_cast<int (*)(int)>( tolower ) (在这种特殊情况下,static_cast并不意味着类型转换,而是显式重载决议。)

在实践中,当然,你不会做这种事情。如果您要进行任何文本处理,您会将所有必要的函数定义为函数对象类型,通过将输入转换为unsigned char

struct ToLower
{
    char operator()( char ch ) const
    {
        return ::tolower( static_cast<unsigned char>( ch ) );
    }
};

或通过使用<locale>do使用的函数char

class ToLower
{
    std::locale myLocale;   //  necessary to guarantee the lifetime of the facet.
    std::ctype const* myCType;
public:
    ToLower( std::locale const& loc = std::locale() )
        ; myLocal( loc )
        , myCType( &std::use_facet<std::ctype>( loc ) )
    {
    }

    bool operator()( char ch ) const
    {
        return myCType->tolower( ch );
    }
};

最后,写下您的第二个问题:差异取决于您使用的 C++ 版本和编译器。然而,全局:<ctype.h> 将函数引入全局命名空间;<cctype>会将它们引入命名空间std::,并且可能(或可能不)引入全局命名空间。(并且您的第三个问题已经在上面得到了回答:std::tolower指的是在<locale>和中定义的一组重载函数<cctype>::tolower指的是在中定义的单个函数<ctype.h>,并且只是tolower等价于 ::tolower除非您已经完成using namespace std,在这种情况下,它将指到上面提到的所有函数的重载集。

于 2012-07-16T08:07:21.693 回答