C ++中的名称冲突

时间:2009-12-04 15:47:36

标签: c++ include g++ definition

在编写一些代码时遇到了这个问题:


#include <iostream>

class random { public: random(){ std::cout << "yay!! i am called \n" ;} };

random r1 ;

int main() { std::cout << "entry!!\n" ; static random r2; std::cout << "done!!\n" ; return 0 ; }

当我尝试编译此代码时,我收到错误
error: ârandomâ does not name a type.
当我为类使用一些不同的名称时,代码工作正常 似乎random在其他地方被定义(尽管编译器消息不是很有用)。

我的问题是如何确保我使用的名称不会与包含文件中使用的名称冲突。我尝试过使用命名空间,但这会在调用时导致模糊不清。 任何见解?
[编辑]
我使用名称空间为using namespace myNSpace
但当我用use myNSpace::random时,它工作得很好。

10 个答案:

答案 0 :(得分:8)

使用命名空间

namespace myNamespace
{

    class random
    {
    public:
        random(){ std::cout << "yay!! i am called \n" ;}
    };

}

myNamespace::random r1;

答案 1 :(得分:5)

您正在使用POSIX random()功能。

你如何避免碰撞?了解你的图书馆。或者你可以按我的方式做到这一点,比如man random。那是随机的(3)。

我不知道你的命名空间问题是什么,但这听起来像是一个单独的问题。

答案 2 :(得分:4)

对于g ++,请使用命令行选项-ansi。这将从stdlib.h中删除非标准函数random

默认情况下,g ++编译为-std=gnu++98,即“1998 ISO C ++标准加上修正加GNU扩展”。所以你的代码没有任何错误,以便可移植。只是没有-ansi,你没有使用兼容的编译器。

这些BSD(和Posix)stdlib函数属于那些GNU扩展。来自glibc文档:

http://www.gnu.org/s/libc/manual/html_node/BSD-Random.html

“在GNU C库中使用这些函数没有任何优势;我们仅支持它们以实现BSD兼容性。”

通常,如果您想编写可移植到不兼容编译器的代码,那么您只需记住世界上每个编译器的特性。 GCC和MSVC是很好的开始。即使使用-ansi,也可以使gcc与其他命令行选项不兼容,例如-O2。这种情况发生在-fdelete-null-pointer-checks惨败一阵闯入Linux内核之后。对于其库“扩展”C(以及C ++)的平台也是如此,如BSD和Posix。

首先有一个C标准的原因应该是你不必担心这些东西,而且我个人认为不幸的是其他标准混淆了C标准的标题。但我猜这些函数在BSD上的stdlib中的事实可以追溯到C89之前。如果是这样的话,那么可能是因为它避免了当时BSD和其他unix的突破性变化。

顺便说一句,我发现random()位于带有g++ -E的stdlib.h中,当你想知道系统标题对你的程序做了什么时,这很有用。我认为在网上搜索“随机”是毫无意义的。但是“stdlib随机”效果很好。

答案 3 :(得分:2)

在我看来,您的特定编译器存在问题。它不会给我很方便的编译器带来错误。

答案 4 :(得分:2)

如果您遇到名称冲突问题,请使用命名空间:

namespace mydata{
 class random{things};
}

然后将其称为mydata::random;

答案 5 :(得分:2)

为什么using namespace...工作时using ...不起作用?首先,我想通过使用详细的类型说明符向您展示另一种解决方法:

int main() {
  // ...
  static class random r2; // notice "class" here
  // ...
}

这是因为“class some_class”是一个精心设计的类型说明符,在查找指定的名称时将忽略任何非类型声明,因此全局范围内具有相同名称的POSIX函数不会隐藏班级名称。您尝试了另外两种方法来解决它:使用指令和使用声明:

  • 然后,您尝试将该类型粘贴到命名空间中,并在main中尝试using namespace foo; - 为什么它不起作用?

    namespace foo {
    class random
    {
     public:
     random(){ std::cout << "yay!! i am called \n" ;}
    };
    }
    
    int main() {
     using namespace foo; 
     static random r2; // ambiguity!
     return 0 ;
    }
    

    您可能想知道为什么会这样,因为您可能认为using指令将foo的名称声明为main的本地范围 - 但事实并非如此。它没有声明任何名称,实际上它只是指向另一个名称空间的链接。在这种情况下,它在非限定名称查找期间使名称可见 - 但是名称作为包含using-directive和表示的名称空间(foo)的命名空间的成员可见。这个封闭的命名空间是这里的全局命名空间。

    所以会发生的是名称查找将找到该名称的两个声明 - 全局POSIX random声明,以及foo中的类声明。声明不是在相同的范围(声明性区域)中进行的,因此函数名称不会像往常一样隐藏类名(有关它的示例,请参阅man stat),但结果是歧义。

  • 使用声明但是声明一个名称作为其出现的声明性区域的成员。因此,从random开始查找main时,它将首先找到一个引用randomfoo声明的名称,这将有效地隐藏全局POSIX函数。以下作品

    namespace foo {
    class random
    {
     public:
     random(){ std::cout << "yay!! i am called \n" ;}
    };
    }
    
    int main() {
     using foo::random; 
     static random r2; // works!
     return 0 ;
    }
    

答案 6 :(得分:1)

要避免这些问题,请使用命名空间 .. wikipedia

namespace myNamespace
{
     class random
     {
         ....
     };
}

答案 7 :(得分:1)

通常,您可以通过明确解决歧义来避免歧义错误。如果没有将重复的符号放在另一个名称空间中,这不起作用(除了详细说明类型说明符帮助litb points out的情况),因为在同一名称空间中有两个符号且无法引用他们中的任何一个都是明确的。

将符号放在命名空间中时,您可以:

  • 完全符合名称:myNamespace::mySymbol(x);
  • 明确解决歧义:using myNamespace::mySymbol;

请注意,通过using myNamespace;从名称空间中提取所有符号无效,因为这无法解决歧义。

对于完全资格认证,通常使用简写名称:

namespace mns = myNamespace;
mns::mySymbol(x);

答案 8 :(得分:0)

你是否包括cstdlib?当我包含它时,我会收到您显示的错误,如果不包含,则不会。

答案 9 :(得分:0)

使用正确编译并运行程序的g ++编译器。我使用MinGw 5.1.6在Windows上运行g ++ ..