Dra*_*rax 44 c++ namespaces class
在类中声明一个类是有效的.(嵌套类)
在类中声明命名空间无效.
问题是:是否有任何好的理由(除了c ++语法/语法问题)禁止在类中声明命名空间?
至于我为什么要这样做,这里有一个例子:
让我们对二叉树容器进行基本的转换
template<typename Data>
class binary_tree
{
public:
... stuff ....
private:
... iterators class declaration ...
public:
typedef left_depth_iterator_impl left_depth_iterator;
typedef right_depth_iterator_impl right_depth_iterator;
typedef left_breadth_iterator_impl left_breadth_iterator;
typedef right_breadth_iterator_impl right_breadth_iterator;
... stuff ....
private:
Data data;
binary_tree* left;
binary_tree* right;
};
Run Code Online (Sandbox Code Playgroud)
现在我注意到我的类中有很多迭代器,所以我想在同一个命名空间中重新组合它们,如下所示:
template<typename Data>
class binary_tree
{
public:
... stuff ....
private:
... iterators class declaration ...
public:
namespace iterator
{
typedef left_depth_iterator_impl left_depth;
typedef right_depth_iterator_impl right_depth;
typedef left_breadth_iterator_impl left_breadth;
typedef right_breadth_iterator_impl right_breadth;
}
... stuff ....
private:
Data data;
binary_tree* left;
binary_tree* right;
};
Run Code Online (Sandbox Code Playgroud)
这将允许一个简单的用法:
void function()
{
binary_tree::iterator::left_depth it;
...stuff...
}
Run Code Online (Sandbox Code Playgroud)
如果我使用类而不是命名空间,这是有效的,但我被迫声明一个永远不会被实例化的类,这是一个非常命名空间.
为什么允许嵌套类并禁止类中的嵌套命名空间?这是传统的负担吗?
具有语义原因而不仅引用部分标准(特别是语法部分)的答案将是apreciated :)
Who*_*aig 46
既然你问过标准命令命名空间位置的哪些部分,我们首先点击它:
C++ 11 7.3-p4:每个命名空间定义都应出现在全局范围或命名空间范围内(3.3.6).
关于类定义和在其中声明命名空间的命题,我带你到...
C++ 11 9.2-p2:在类说明符的结束时,类被认为是完全定义的对象类型(3.9)(或完整类型).在类成员规范中,对于非静态数据成员(包括嵌套类中的此类事物),该类在函数体,缺省参数,异常规范和大括号或大小写初始化中被视为完整.否则,它在其自己的类成员规范中被视为不完整.
因此,一旦达到收尾卷曲,类定义就是有限的.它不能打开备份和扩展(派生是不同的,但它不是扩展刚刚定义的类).
但潜伏在命名空间标准定义的最开始的是扩展它的能力; 为了缺乏一个更好的术语来扩展它:
C++ 7.3-p1:命名空间是一个可选命名的声明性区域.命名空间的名称可用于访问在该命名空间中声明的实体; 也就是命名空间的成员.与其他声明性区域不同,命名空间的定义可以分为一个或多个转换单元的几个部分.(重点补充).
因此,类中的命名空间将违反7.3-p4中的定义.假设不存在,可以在任何地方声明一个命名空间,包括在一个类中,但由于一个类的定义一旦关闭就形式化了,如果你维护它,你将只能做以下事情.符合7.3-p1:
class Foo
{
namespace bar
{
..stuff..
}
.. more stuff ..
namespace bar
{
..still more stuff..
}
};
Run Code Online (Sandbox Code Playgroud)
在建立7.3-p4以解决它之前,这个特征的有用性可能会争论大约3整秒.
Ers*_*oat 14
我在这里不同意其他人的意见.我不会说没有真正的优势.有时我只是想分离代码而没有额外的含义.作为一个例子,我在一个多线程的ringbuffer模块中工作,并希望将状态成员(其中一些是原子和/或内存对齐)拆分为生产者和消费者的命名空间.
通过命名所有内容producer
或consumer
前缀(这是我当前讨厌的实现),我添加污染,使代码更难阅读.例如,当生产者拥有的所有东西都开始时producer
,你的大脑在阅读它时会更容易自动更正producerProducerTimer
(生产者计时器的生产者副本)作为producerConsumerTimer
(消费者计时器的生产者阴影)或consumerProducerTimer
(生产者计时器的消费者阴影).调试时间比需要的时间长,因为代码不再可以浏览.
通过创建嵌套的类/结构:
= delete
这些东西.理想情况下,我希望能够改变这样的事情:
rbptr producerPosition;
rbptr consumerPosition;
Run Code Online (Sandbox Code Playgroud)
对此:
namespace producer
{
rbptr position;
}
namespace consumer
{
rbptr position;
}
Run Code Online (Sandbox Code Playgroud)
然后,只应触及使用者成员的函数可以使用使用者名称空间,只应触及生成者成员的函数可以使用生成器名称空间,而需要触及两者的函数必须明确限定它们.在仅使用producer命名空间的函数中,无法意外触摸消费者变量.
在这种情况下,希望纯粹是为了减少生产者和消费者副本之间的命名冲突,减少命名冲突是存在名称空间的.出于这个原因,我支持能够在类中声明名称空间的提议.
将这样的功能添加到语言中没有任何实际优势.除非有需求,否则通常不会添加功能.
课程中的命名空间会给你带来什么?你真的宁愿说binary_tree::iterator::left_depth
而不是简单binary_tree::left_depth
吗?也许如果你有多个名称空间,你可以使用它们区分说binary_tree::depth_iterator::left
和binary_tree::breadth_iterator::right
.
无论如何,你可以使用内部类作为一个程序员的命名空间来实现所需的结果,这更是为什么在类中不需要真正的命名空间的原因.