16

我只使用特定于 C++ 的头文件(例如<cstdlib>),但是我仍然得到全局声明的函数,而不仅仅是std命名空间中的函数。有没有办法(也许是编译器开关)来防止这种情况?

例如,下面的代码:

#include <cstdlib>
float random() { return 0.0f; }
int main() { return 0; }

linux下编译失败,报如下错误:

> g++ -c main.cpp main.o
main.cpp: In function ‘float random()’:
main.cpp:2:14: error: new declaration ‘float random()’
/usr/include/stdlib.h:327:17: error: ambiguates old declaration ‘long int random()’

或者

> clang++ main.cpp -o main.o
main.cpp:2:7: error: functions that differ only in their return type cannot be overloaded
float random() { return 0.0f; }
/usr/include/stdlib.h:327:17: note: previous declaration is here
extern long int random (void) __THROW;

这是因为它自己的功能stdlib.h“污染”了全局命名空间。random

请注意,在 Windows 上使用 Visual Studio 进行编译时,我不会遇到这些问题。

4

5 回答 5

10
  1. <cstdlib>总是会填充 std 命名空间,有时会定义全局符号,而<stdlib.h>总是会定义全局符号,有时会填充 std 命名空间。这因实施而异。

  2. 标准写道:

    每个 C 标头都有一个名为 form 的名称,其name.h行为就好像每个由相应cname标头放置在标准库命名空间中的名称都放置在全局命名空间范围内一样。未指定这些名称是否首先在命名空间的命名空间范围(3.3.6)内声明或定义,std然后通过显式使用声明(7.3.3)注入全局命名空间范围。

    这意味着,允许编译器同时将这些符号放入全局范围和std命名空间。

  3. 因此,我们认为选择一个头文件优于另一个头文件没有任何优势。因为它们都极有可能污染全局范围

    但是,仍然需要使用std命名空间 when#include <cstdlib>并且不要使用stdwhen #include <stdlib.h>,以确保您的代码可以针对所有编译器实现进行编译。

  4. 建议:不要在标准库中使用名称。首先,它们不能保证工作。(注意:很少有编译器实现真正保持全局范围清洁#include <csomething>,所以永远不要依赖它。)其次,它会使代码阅读者和维护者感到困惑,因为几乎每个人都会认为标准名称实际上是标准的,无论它们来自哪里。

于 2013-10-25T11:14:58.400 回答
6

您可以在自己的命名空间中声明您的函数,以防止声明冲突。

namespace MyFunc
{
float random() { return 0.0f; }
};
于 2013-10-25T10:40:02.600 回答
3

一般来说,您首先应该尽量避免重新声明。您可以通过使用命名空间或将源代码拆分为可以包含的文件cstdlib和其他可以使用static(名称冲突)函数版本的文件来做到这一点。

如果这不是一个选项,请继续阅读。但请注意,以下内容可能非常特定于平台。

通过查看 mycstdlibstdlib.hhere at my place,我注意到有一个开关cstdlib决定它是包含stdlib.h还是仅声明abort,atextexitstd命名空间中。

显然,您拉入了stdlib.h分支。进一步查看这个文件,我注意到了宏__BEGIN_NAMESPACE_STD,后来又注意到了__END_NAMESPACE_STD. 也许你可以使用它,但它(顾名思义)是一些实现内部宏,不应该由你直接设置。但是,由于某种原因它应该在那里,因此您可能会幸运地找到它。

经过一番搜索,结果发现这random是几个未包装到__BEGIN_NAMESPACE_STD. 因此,这不是问题的解决方案。_GLIBCPP_USE_NAMESPACES(我发现了另一个似乎也在内部使用的宏#define __BEGIN_NAMESPACE_STD namespace std {)。

所以总结一下:这不是可行的路径,您应该使用所描述的解决方法之一。

于 2013-10-25T10:54:28.700 回答
2

该标准明确允许<c???>标头将 C 标准函数的名称带入全局命名空间。

于 2013-10-25T10:49:12.397 回答
0

通常我宁愿让你的函数名与定义为标准的不同。例如,这里可以使用函数名称作为 myRandom 而不是 random,这样我就可以通知那些将在以后维护我的代码的人,正在使用的函数不是定义为标准的函数。

于 2013-10-25T10:42:52.317 回答