使用c函数时C ++中的命名空间

时间:2012-07-16 06:20:04

标签: c++ c namespaces

  

可能重复:
  unresolved overloaded function type 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);
}

使用G ++编译时出现tolower错误:未解决的重载功能

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

然后,我的问题是:

  • namespace std与C函数之间的关系是什么?
  • #include<ctype.h>#include<cctype>之间有什么区别?虽然它们都不适用于上面的例子。
  • 为什么std::tolower也不起作用? std::tolowertolower之间的区别是什么?

2 个答案:

答案 0 :(得分:4)

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

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

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

至于为什么std::tolower不起作用,我不知道。 The example of cpp reference不使用std::transform,这可能是原因。

答案 1 :(得分:4)

namespace std和C函数之间没有关系。但 你的代码不是C,它是C ++,所以你还必须考虑C ++函数。 与std::tolower类似,例如<locale>。你的问题是由于 事情的一致:

  • 您添加的其中一个标题包含<locale>。 C ++标题是 允许包含其他C ++标头,以及哪个标头包含哪些标头 其他标题可能因实现而异,所以 你编写的代码可以用一个编译器编译,而不是用 另一

  • 您正在尝试将该函数作为指向函数参数的指针传递, 到函数模板,其中参数是模板类型 参数。简单地说,为了做超载分辨率 tolower这里,编译器必须将它与类型相匹配 参数,以及为了知道参数的类型,编译器 必须根据确切的类型进行模板类型推导 函数,只有在完成重载解析后才能知道。

如果你想要<ctype.h>中的功能(你没有,因为它会 导致未定义的行为),你可以通过包括得到它 <ctype.h>(保证它存在于全球 命名空间)并使用::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>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 );
    }
};

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