类命名空间
Class namespace?
是我还是C++中面向对象范式的实现缺少类命名空间的概念?
以下是我的意思的一个例子:
文档 { 页眉 {} 正文 {}页脚 {} }
文档是可以具有页眉、正文和页脚的对象。
从外部命名空间处理此类对象及其元素的一种直接方法是
- 公文
- 文档::页眉
- 文档::正文
- 文档::页脚
有没有办法在不限制文档类定义的情况下C++实现这种命名结构?
1) 命名空间文档 { ... }
这种情况需要在其自己的命名空间中有一个对象类,并且使用 Document::D ocument 似乎是多余的和无意的。
2) 命名空间 文档 { 类 ... } typedef 文档::D ocument document;
这种情况给出了文档和文档::{part},在大小写中,敏感的语言可能看起来很奇怪且无关。
3) 类文档 { 类 ... };
这种情况需要在每个嵌套类的定义中包含文档标头,并且不允许使最终对象成为其部分的派生物,因为它们是在其自己的范围内定义的。
4) 类文档 { 类 ... };类文档:公共文档{}
这种情况接近预期,但需要额外的类和继承。
!理想情况下,我想要的是
namespace class Document {
class Header;
class Body;
class Footer;
class Document; // linked with the parent namespace as with its own name space
}
Document doc; // ok, resolves Document as a class
Document::{Part} docPart; // ok, resolves Document as namespace
.)有没有其他合理的方法可以在不产生不合理的额外费用的情况下实现预期目标?
我也不确定为什么这些琐碎的事情不是一种标准的方法。有什么具体原因吗?
---澄清---
为了解决提出的一些问题,
"有什么用?"1)通俗语言 2)从语言构造到对象的抽象模型的透明映射,反之亦然。
"为什么要从物体的各个部分推导出一个物体?"并非对象引入的每个实体都必须是其部分。例如,它可以是它的本质。例如:
文档 { 骨架{} 部件 { 页眉 {} 正文 {}页脚 {
} } }
---抽象框架---
将对象视为一个模块,其定义可以使用外部符号并引入自己的一些符号以及自己的逻辑实体的定义,因为它们应该保持相关,因为它引入了它们。
---点---
整个模块是一个对象的定义。能够在没有任何额外的语言嘲笑的情况下使用它会很好。
=== 分辨率 ===
感谢您的反馈。
在C++有办法将命名空间名称链接到类之前,我想我会使用
对象名称{ ...Object {} } -> ObjectName::Object,ObjectName::Part
在这种情况下构造。它可能没有我想的那么短,但至少足够透明,没有额外的成本,并且可以与前向声明一起使用。
您的第三个选项 - 使用嵌套类声明/定义,将为您提供所需的理想范围分辨率(尽管它不会涉及单个命名空间)。
class Document
{
public:
class Header
{
// Header class declaration here
};
class Body
{
// Body class declaration here
};
class Footer
{
// Footer class declaration here
};
// Document declaration here.
};
您对此选项的担忧是:
要求在每个嵌套类的定义中包含文档标头
是的 - 嵌套类与周围的类有着千丝万缕的联系,它们的实现将取决于周围类的定义,因为它包含嵌套类的定义。 这是不可避免的。
Dpesn不允许使最终对象成为其部分的派生物,因为它们是在自己的范围内定义的。
你试图做的事情似乎没有什么逻辑意义——你试图根据它自己的部分来定义某物,这是一个循环定义。 通过从页眉、正文或页脚派生文档,您想实现什么目的?
您问题的最后一行表明您发现所需的功能"微不足道",但在我看来和经验来看,这远非微不足道。由于语法相似性,您似乎将命名空间和类混为一谈,但它们是完全不同的概念。 您必须在脑海中将两者分开,除了一些范围效应和范围解析语法外,它们几乎没有重叠。 您的"文档"必须是命名空间和类。 选择一个;) (从技术上讲,实际上可以同时拥有命名空间文档和类文档,但这可能会造成混淆。 )
你的第一种情况完全按照你所说的去做。Document::Document
没有什么多余的 - 它指的是Document
命名空间中的Document
类。XML
命名空间中很可能有一个 Document 类,MyCompany
命名空间中很可能有一个 Document 类。
第二种情况看起来像是试图从根本上破坏使用命名空间的目的。如果您不想使用命名空间,请不要 - 只需使用全局(未指定)命名空间并冒冲突的风险。如果只想避免代码中与Document
类相关的Document::
部分,请在该代码中添加using namespace Document
指令。
您只需将零件类包含在Document
类中即可。
class Document {
public:
class Header;
class Body;
class Footer;
};
您可以有效地使用它:
Document myDoc; // Type Document
Document::Header myHeader;
3) class Document { class ... };
这种情况需要在每个嵌套类的定义中包含文档标头,并且不允许使最终对象成为其部分的派生物,因为它们是在其自己的范围内定义的。
不,这种设计是最有意义的。我不明白你认为class
和namespace class
之间的区别是什么.
class Document
{
public:
class Header
{
};
Header m_header;
class Body
{
};
Body m_Body;
};
这个设计有什么问题?您可以通过Document::Header
访问这些类型。您可以通过myDocument.m_header
等实例进行访问。
唯一固有的奇怪之处在于你不能将类型和成员变量命名为相同,但是有很多方法可以解决这个问题,这实际上是一个肤浅的限制。
仅仅因为Document
对象包含Header
对象并不意味着Header
类应该包含在Document
类中。至少,这通常不会这样做。
我只会在极少数情况下嵌套类;也就是说,当嵌套类是外部类的实现细节并且不向外部世界公开时(但即便如此,放弃嵌套也很常见)。
顺便说一下,这与C++无关:除了隐藏实现细节之外,类通常很少嵌套。像您一样,对对象关系进行建模的框架通常不会使用嵌套。相反,您可能有如下所示的内容:
namespace Html {
class Document;
class Header;
class Body;
// …
}
C++特别使用平面命名空间层次结构,但上述内容同样适用于 C# 或 Java。
最后,明确回答您的介绍性问题:
是我还是面向对象范式的实现C++缺少类命名空间的概念?
C+ 与其他现代 OO 语言具有相同的概念:类形成一个命名空间,用于名称查找,以便您可以实现所需的目标。但出于上述原因,我认为这不是一个特别理想的目标。
我不完全清楚你想公开多少嵌套的 类,但如果它们是Document
的一部分,它们可能应该是 嵌套类。 你的意思的例子,在你的开头 代码,正是人们在C++中执行此操作的方式:
class Document
{
public: // or not?
class Header
{
};
class Body
{
};
class Footer
{
};
};
关于我能看到的唯一反对意见是仅实现文件 关注Document::Header
必须包括整个Document
类定义,但我认为这不是一个主要问题;如果Document::Header
真的不是独立的,那么似乎合理 需要这个。 关于你对此解决方案的第二个反对意见: 你永远不想让一个对象从它的部件派生:一个Document
哈斯·Header
;这不是一种是关系。
如果单独使用Header
等人确实有意义,那么 最好的解决方案是在Document
类之外定义它们,要么 赋予它们更具描述性的名称(例如DocumentHeader
) 或包装 它们位于一个特殊的命名空间中(例如namespace DocumentParts
)。 取决于 关于他们与Document
的关系,使用可能是有意义的typedef
Document
,以便它们可以称为DocumentParts::Header
或Document::Header
.
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- CUDA内核和数学函数的显式命名空间
- 嵌套的匿名命名空间
- CMakeLists.txt中的命名空间表示法
- 类是C++中的命名空间吗
- 在命名空间中使用全局命名空间中的函数
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 是否可以将函数导入命名空间,但不能导出它?
- C++ C++类中的命名空间降级
- 如何使用 soong 命名空间来有条件地编译模块
- 使用 Clang++ 有没有办法将文件作为命名空间等包含?
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何通过命名空间调用非静态方法
- 在命名空间名称之前加上 :: 是什么意思?