3

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


#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它工作正常。

4

10 回答 10

8

使用命名空间

namespace myNamespace
{

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

}

myNamespace::random r1;
于 2009-12-04T15:51:48.457 回答
5

您正在运行 POSIXrandom()函数。

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

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

于 2009-12-04T15:53:29.733 回答
4

在 g++ 的情况下,使用命令行选项-ansirandom这从 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”效果很好。

于 2009-12-04T16:00:59.283 回答
2

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

于 2009-12-04T15:50:33.750 回答
2

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

namespace mydata{
 class random{things};
}

然后调用它mydata::random;

于 2009-12-04T15:52:33.917 回答
2

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

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

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

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

    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 指令和表示的名称空间 ( foo) 的名称空间的成员可见。封闭的命名空间就是这里的全局命名空间。

    所以发生的事情是名称查找将找到该名称的两个声明 - 全局 POSIXrandom声明和foo. 声明不是在相同的范围(声明性区域)中进行的,因此函数名不会像往常一样隐藏类名(参见man stat示例),但结果是模棱两可的。

  • 但是using声明将一个名称声明为它出现的声明性区域的成员。因此,当random从 开始查找时main,它将首先找到一个引用 in 声明的名称,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 ;
    }
    
于 2009-12-04T17:20:55.160 回答
1

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

namespace myNamespace
{
     class random
     {
         ....
     };
}
于 2009-12-04T15:53:48.190 回答
1

通常,您可以通过显式解决歧义错误来避免歧义错误。如果不将重复的符号放在另一个命名空间中,这是行不通的(除了litb 指出的详细类型说明符有帮助的情况),因为您在同一个命名空间中有两个符号并且不能明确引用它们中的任何一个。

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

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

请注意,从您的命名空间中提取所有符号 viausing myNamespace;无济于事,因为这不能解决歧义。

为了获得完整的资格,通常使用简写名称:

namespace mns = myNamespace;
mns::mySymbol(x);
于 2009-12-04T17:07:05.530 回答
0

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

于 2009-12-04T16:18:41.353 回答
0

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

于 2009-12-04T16:35:26.653 回答