在内部定义的未命名(匿名)命名空间之外定义函数或类成员的实现是否合法。 我的编译器接受它但我想确定它是合法的 e.g。
////////////////
// foo.cpp
namespace {
struct X
{
void foo(int x);
};
}
// Is this legal?
void X::foo(int x)
{
}
原因是我想避免因我们的解密格式而施加的不必要的缩进
答案 0 :(得分:4)
这与以下内容没有什么不同,这完全是合法的:
namespace ns {
struct s {
void f();
};
}
using namespace ns;
void s::f() { }
命名命名空间中的名称被带入全局命名空间,因此可以为它们提供定义。与未命名的命名空间的唯一区别是它没有名称(实际上,它有一些唯一的,不可知的名称),using namespace
是隐式的。
答案 1 :(得分:0)
#include <iostream>
using namespace std;
namespace
{
struct X
{
X(int);
int x_;
};
}
X::X(int x) : x_(x) {}
int main()
{
X x(5);
cout << x.x_ << "\n";
return 0;
}
在gcc 4.6.0下编译(并运行)
答案 2 :(得分:0)
是。这完全合法。 未命名命名空间的区别在于,命名空间的内容仅在其声明的文件中可用。如果它在.h
文件中,则会将其添加到所有后续.cpp
文件中,并且每个.cpp
文件都将具有namespace
内容的唯一副本。 / p>
实际上,这是一种声明全局static
变量的更好方法。现在看,它会产生什么样的差异:
namespace {
struct X
{
void foo(int x);
};
int i; // declare this global variable
}
如果您将此代码放在头文件中,那么无论该头文件是#include
,所有这些.cpp
文件都会在其中包含int i;
的不同副本。在一个i
文件中更改.cpp
的值不会影响其他.cpp
文件。
此外,它不会为多个定义提供链接器错误,因为它在未命名的namespace
中。
编辑:要对其进行更多评估,请按以下方式定义命名空间:
// x.h
namespace
{
struct X
{
void foo(int x)
{
static int c; // static inside the function
cout<<"a = "<<(c++)<<endl;
}
};
}
现在#include
此标头文件包含2个不同的.cpp
个文件。在他们两个中尝试使用foo()
的对象调用X
。它会打印出来:
a = 0
a = 0
这意味着 X::foo()
文件中的.cpp
不同。如果您给namespace
一个名字并重复同样的事情,它将输出
a = 0
a = 1
因此,未命名的namespace
会为每个翻译单元创建不同的副本。
答案 3 :(得分:0)
在您的方案中它是合法的,但在一种情况下,它会导致编译器模糊错误。
如果在X.h中有另一个类:
// X.h
struct X
{
void foo(int x) { }
};
在foo.cpp中,需要使用X.h中定义的X
////////////////
// foo.cpp
#include "X.h"
namespace {
struct X
{
void foo(int x);
};
// use the X declared in anonymous namespace
void test()
{
X x;
x.foo(3);
}
}
// reference to 'X' is ambiguous
void X::foo(int x)
{
}
void otherFunction()
{
// Use struct X in X.h
::X x;
x.foo(3);
}
如果将实现代码留在匿名命名空间之外,编译器会抱怨含糊不清。如果将实现代码移到匿名命名空间中,它可以正常工作。