看起来不可能在类中声明命名空间别名;但是我们可以在函数级别这样做(使用 g++ 4.3.4 测试):
namespace A
{
}
class C
{
namespace N = A; // error: expected unqualified-id before `namespace'
};
class D
{
void f();
};
void D::f()
{
namespace N = A; // OK
}
知道为什么存在这样的限制吗?这似乎与可以在类中声明的 typedef 不太一致。
根据C++标准3.3.6
以下规则描述了类中声明的名称的范围。
1) 类中声明的名称的潜在范围不仅包括名称声明符后面的声明区域,还包括该类中的所有函数体、默认参数和构造函数初始化器(包括嵌套类中的此类内容) )。 …………
因此,您只能在类作用域中声明此列表中的内容。在类范围内声明任何其他内容都是无效的。不仅仅是命名空间联盟,还有命名空间。例如
class myClass
{
//compilation error !!!
namespace myNamespace
{
}
using namespace std;//another compilation error
}
编辑:
知道为什么存在这样的限制吗?这似乎与可以在类中声明的 typedef 不太一致。
因为在类中使用 typedef 非常有用(例如
vector<int>::iterator
),而对于命名空间来说则毫无用处。考虑以下代码
class myClass
{
namespce N=std;
};
//now let's use N
MyClass::N::vector<int> v;//don't you think, that this syntax is horrible, and useless?????
为了进行比较,请查看它在功能中做了什么
void f()
{
namespace bnu= boost::numeric::ublas;
bnu::matrix<int> m;//and now we can use short name bnu
}
对于类,我们可以在 cpp 文件中声明命名空间联盟,并且无需在类声明中声明它。
我不是 C++ 标准方面的专家,但我会尽力回答你的问题。我认为在类声明中使用
namespace N = A
不符合如何定义类成员的定义。
C++ 标准将类成员定义为
member-specification:
member-declaration member-specification_opt
access-specifier : member-specification_opt
member-declaration:
decl-specifier-seq_opt member-declarator-list_opt ;
function-definition ;opt
::opt nested-name-specifier templateopt unqualified-id ;
using-declaration
static_assert-declaration
template-declaration
member-declarator-list:
member-declarator
member-declarator-list , member-declarator
member-declarator:
declarator pure-specifier_opt
declarator constant-initializer_opt
identifier_opt : constant-expression
pure-specifier:
= 0
constant-initializer:
= constant-expression
重要的一点是声明中的
=
,编译器期望纯说明符或常量初始化语句,并且由于该行不以零结尾,因此在这种情况下我们不应用纯说明符。
分析编译器将其视为的
namespace N = A
声明
declarator = constant-expression
并且由于
namespace
是一个关键字,因此不能使用。
typedef
是允许的,因为(根据标准)
嵌套类型是类和类中定义的枚举, 以及使用 typedef 声明声明为成员的任意类型。
我不同意类中的名称空间声明完全没有用。能够在类的命名空间内声明枚举会很有用。这将允许您使用特定数组的逻辑索引访问不同数组的元素。
class myClass
{
private:
namespace TransAndRotIdx {
enum { U, V, W, P, Q, R }; };
namespace RotIdx {
enum { P, Q, R }; };
double tr[6];
double r[3];
public:
double getTranslationMag(void)
{
using namespace TransAndRotIdx;
return sqrt(tr[U]*tr[U]+tr[V]*tr[V]+tr[W]*tr[W]);
}
double getRotationMag(void)
{
using namespace RotIdx;
return sqrt(tr[P]*tr[P]+tr[Q]*tr[Q]+tr[R]*tr[R]);
}
}