代码之家  ›  专栏  ›  技术社区  ›  sud03r

C++中的名称冲突

  •  3
  • sud03r  · 技术社区  · 15 年前

    在编写代码时,我遇到了这个问题:

    
    #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 回复  |  直到 15 年前
        1
  •  2
  •   Johannes Schaub - litb    15 年前

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

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

    这是因为“class some_class”是一个详细的类型说明符,在查找指定的名称时,它将忽略任何非类型声明,因此全局范围内同名的posix函数不会隐藏类名。您尝试了其他两种方法来解决它:使用指令和使用声明:

    • 然后,您尝试将类型粘贴到命名空间中,并尝试 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 在当地的主要范围内-但事实并非如此。它不声明任何名称,实际上它只是到另一个名称空间的链接。在这种情况下,它使名称在非限定名称查找期间可见-但该名称作为包含using指令和指示名称空间的名称空间的成员可见( )这个封闭的名称空间就是这里的全局名称空间。

      因此,名称查找将找到该名称的两个声明-全局posix random 声明和类声明 . 声明不是在同一个作用域(声明性区域)中进行的,因此函数名不会像往常一样隐藏类名(请参见 man stat 但结果是一个模棱两可的例子。

    • A使用 宣言 但是,将一个名称声明为它出现在的声明性区域的成员。所以,什么时候 随机的 从开始查找 main ,它将首先找到一个引用 随机的 在里面 FOO公司 ,这将有效地隐藏全局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 ;
      }
      
        2
  •  8
  •   karoberts    15 年前

    使用命名空间

    namespace myNamespace
    {
    
        class random
        {
        public:
            random(){ std::cout << "yay!! i am called \n" ;}
        };
    
    }
    
    myNamespace::random r1;
    
        3
  •  5
  •   Warren Young    15 年前

    你碰到了POSIX random() 功能。

    如何避免碰撞?了解你的图书馆。或者你可以像我诊断的那样,说 man random . 在那里,随机(3)。

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

        4
  •  4
  •   Steve Jessop    15 年前

    在G++的情况下,使用命令行选项 -ansi .这将删除非标准功能 random 来自stdlib.h.

    默认情况下,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() 在stdlib.h中 g++ -E ,这在您想要了解系统头文件对您的程序究竟做了什么时非常有用。我认为在网络上搜索“随机”是没有意义的。但是“stdlib random”工作得很好。

        5
  •  2
  •   Jerry Coffin    15 年前

    在我看来,您的特定编译器有问题。它不会给我手边的编译器带来错误。

        6
  •  2
  •   Arkaitz Jimenez    15 年前

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

    namespace mydata{
     class random{things};
    }
    

    然后叫它 mydata::random;

        7
  •  1
  •   Jack    15 年前

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

    namespace myNamespace
    {
         class random
         {
             ....
         };
    }
    
        8
  •  1
  •   Community CDub    8 年前

    通常,通过显式地解决歧义错误,可以避免歧义错误。如果不将重复的符号放在另一个命名空间中,这将无法工作(除非 详细的类型说明符 作为帮助 litb points out )因为您在同一个名称空间中有两个符号,并且不能显式引用它们中的任何一个。

    将符号放入命名空间时,可以:

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

    请注意,通过从命名空间中提取所有符号 using myNamespace; 没有帮助,因为这不能解决歧义。

    对于完全限定,通常使用简称:

    namespace mns = myNamespace;
    mns::mySymbol(x);
    
        9
  •  0
  •   Liz Albin    15 年前

    您是否包括CSTDlib?当我把它包括在内时,我会得到你显示的错误,如果不包括,我不会。

        10
  •  0
  •   Vaibhav    15 年前

    我使用的g++编译器已经正确编译并运行了您的程序。我正在使用mingw 5.1.6在Windows上运行g++。