我只使用特定于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
函数的全局命名空间。
请注意,在使用Visual Studio在Windows上进行编译时,我不会遇到这些问题。
答案 0 :(得分:10)
<cstdlib>
将始终填充std命名空间,有时会定义全局符号,而<stdlib.h>
将始终定义全局符号,有时会填充std命名空间。这从实施到实施各不相同。
标准写道:
每个C头(每个头都有一个
name.h
形式的名称,就好像每个由相应的cname
标头放置在标准库名称空间中的名称放在全局名称空间范围内。 未指定是否首先在名称空间std
的名称空间范围(3.3.6)中声明或定义这些名称,然后通过显式使用声明将其注入全局名称空间范围(7.3 0.3)。
这意味着,允许编译器 将这些符号同时放入全局范围和std
命名空间 。
因此,我们认为优先选择一个头文件而不是另一个头文件没有任何优势。因为他们都很可能污染全球范围。
但是,在std
时仍然需要使用#include <cstdlib>
命名空间,而在std
时不要使用#include <stdlib.h>
,以确保您的代码可以为所有编译器编译的实施方式。
建议:不要在标准库中使用名称。首先,他们不能保证工作。 (注意:很少有编译器实现在#include <csomething>
时实际上保持全局范围干净,所以永远不要依赖于此。)其次,它会使代码阅读器和维护者感到困惑,因为几乎每个人都会认为标准名称实际上是标准名称,无论如何他们来自哪里。
答案 1 :(得分:6)
您可以在自己的命名空间中声明您的函数,以防止声明冲突。
namespace MyFunc
{
float random() { return 0.0f; }
};
答案 2 :(得分:3)
一般情况下,您应该尽量避免重新声明。
您可以通过使用命名空间或将源拆分为包含cstdlib
的文件和其他可以使用(名称冲突)函数的static
版本的文件来完成此操作。
如果这不是一个选项,那么继续阅读。但请注意,以下内容可能非常特定于平台。
通过在我的位置查看我的cstdlib
和stdlib.h
,我注意到有cstdlib
决定是否包含stdlib.h
或只是在abort
命名空间中声明atext
,exit
和std
。
显然你拉入了stdlib.h
分支。进一步查看此文件,我注意到宏__BEGIN_NAMESPACE_STD
以及稍后的__END_NAMESPACE_STD
。也许你可以使用它,但它(顾名思义)是一些实现内部宏,不应该由你直接设置。但是,它应该出于某种原因,所以你可能有幸找到它。
经过多次搜索后发现random
是几个未包含在__BEGIN_NAMESPACE_STD
中的函数(和声明)之一。因此,这不是问题的解决方案。 (我发现了另一个宏_GLIBCPP_USE_NAMESPACES
,它似乎也在内部用于#define __BEGIN_NAMESPACE_STD namespace std {
)。
总而言之:这不是可行的路径,您应该使用上述解决方法之一。
答案 3 :(得分:2)
标准明确允许<c???>
标头将C标准函数的名称带到全局名称空间。
答案 4 :(得分:0)
通常我更希望保持您的功能名称与定义为标准的名称不同。 对于ex在这里,可以使用函数名称作为myRandom而不是随机,这样我可以通知那些将在稍后维护我的代码的人,使用的函数不是定义为标准的函数。