类命名空间?

时间:2012-09-25 09:18:52

标签: c++ oop lang

是我还是C ++中面向对象范式的实现缺少类命名空间的概念?

这是我的意思的一个例子:

  

文档{标题{}正文{}页脚{}}

Document是一个可以有标题,正文和页脚的对象。

从外部名称空间处理此类对象及其元素的直接方法是

  • 文档
  • 文档::页眉
  • 文献::体
  • 文献::页脚

有没有办法在C ++中实现这样的命名结构而不对Document类的定义施加限制?

1)namespace Document {...}

这种情况需要在其自己的命名空间内使用对象类,并且使用Document :: Document似乎是多余的和无意的。

2)namespace Document {class ...} typedef Document :: Document document;

本案例给出了文档和文档:: {part},以防敏感语言看似奇怪且无关。

3)class Document {class ...};

这种情况要求在每个嵌套类的定义中包含Document头,并且不允许使最终对象成为其部分的衍生物,因为它们是在自己的范围内定义的。

4)班级文件{class ...}; class Document:公共文档{}

这种情况接近预期,但需要额外的类和继承。

!)理想情况下,我想拥有的是

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)从语言构造到对象抽象模型的透明映射,反之亦然。

“为什么要从其各个部分派生一个对象?”并非对象引入的每个实体都必须是它的一部分。例如,它可能是它的本质。 E.g:

  

文档{Skeleton {} Parts {Header {} Body {} Footer {}}}

---抽象框架---

将一个对象想象成一个模块,它的定义可以使用外部符号,并引入它自己的一些符号以及它自己的逻辑实体的定义,因为它们引入它们应该保持相关。

---点---

整个模块是对象的定义。如果没有任何额外的语言嘲笑,能够使用它会很好。

=== resolution ===

感谢您的反馈。

直到C ++中有一种方法将命名空间名称链接到一个类,我想我会用

  

ObjectName {... Object {}} - > ObjectName :: Object, ObjectName :: Part

在这种情况下构建。它可能没有我想要的那么短,但至少足够透明,没有额外费用,并且可以与前向声明一起使用。

6 个答案:

答案 0 :(得分:6)

您的第三个选项 - 使用嵌套类声明/定义,将为您提供理想的范围解析(尽管它不涉及单个命名空间)。

class Document 
  {
  public:
    class Header
      {
      // Header class declaration here
      };

    class Body
      {
      // Body class declaration here
      };

   class Footer
      {
      // Footer class declaration here
      };

    // Document declaration here.
  };

您对该选项的担忧是:

要求在每个嵌套类的定义中包含Document标头

是 - 嵌套类与周围的类密不可分,它们的实现将取决于周围类的定义,因为它包含嵌套类的定义。这是不可避免的。

Dpes不允许使最终对象成为其各部分的衍生物,因为它们是在自己的范围内定义的。

你要做的事似乎没有什么逻辑意义 - 你试图根据自己的部分定义一些东西,这是一个循环的定义。你想通过从页眉,正文或页脚派生文件来实现什么目标?

你问题的最后一行表明你发现你想要的功能“微不足道”,但在我看来,这并不是微不足道的。由于语法上的相似性,您似乎在混淆命名空间和类,但它们是完全不同的概念。您必须将两者分开,除了一些范围效果和范围分辨率语法之外,它们几乎没有重叠。您的“文档”必须是命名空间和类。选择一个;)(从技术上讲,它实际上可能同时具有命名空间Document和类Document,但这很可能是混乱的根源。 )

答案 1 :(得分:2)

你的第一个案件正是你所说的。 Document::Document没有任何多余的内容 - 它引用Document命名空间中的Document类。 XML命名空间中可能有一个Document类,而MyCompany命名空间中可能有另一个。

你的第二个案例看起来像是试图破坏使用命名空间的目的。如果您不想使用命名空间,请不要 - 只使用全局(未指定)命名空间和风险冲突。如果您只想避免与Document::类相关的代码中的Document部分,请在该代码中添加using namespace Document指令。

答案 2 :(得分:1)

  

3)class Document {class ...};

     

这种情况要求在每个嵌套类的定义中包含Document头,并且不允许使最终对象成为其部分的衍生物,因为它们是在自己的范围内定义的。

不,这种设计是最有意义的。我不明白您认为classnamespace class之间存在差异。

class Document
{
public:
    class Header
    {
    };

    Header m_header;

    class Body
    {
    };

    Body m_Body;
};

这个设计有什么问题?您可以通过Document::Header访问这些类型。您可以通过myDocument.m_header等实例进行访问。

唯一固有的奇怪之处在于你不能将类型和成员变量命名为相同,但是有很多方法可以解决这个问题,而且这实际上是一种肤浅的限制。

答案 3 :(得分:1)

您只需将部分类括在Document类中。

class Document {
public:
   class Header;
   class Body;
   class Footer;
};

您可以有效地使用它:

Document myDoc;   // Type Document
Document::Header myHeader;

答案 4 :(得分:1)

仅仅因为Document 对象包含Header 对象并不意味着Header 类< / em>应包含在Document 中。至少,通常不会这样做。

我只会在极少数情况下嵌套类;也就是说,当嵌套类是外部类的实现细节时,并且不暴露给外部世界(但即使这样,放弃嵌套也是常见的)。

顺便说一句,这与C ++无关:除了隐藏实现细节之外,通常很少嵌套类。在您的情况下建模对象关系的框架通常不会使用嵌套。相反,你可能会有这样的事情:

namespace Html {
    class Document;
    class Header;
    class Body;
    // …
}

C ++特别使用平面命名空间层次结构,但上述内容同样适用于C#或Java。

最后,要明确地解决您的介绍性问题:

  

是我还是C ++中面向对象范式的实现缺少类命名空间的概念?

C +与其他现代OO语言具有相同的概念:一个类形成一个命名空间,用于名称查找,因此可以实现你想要的。但由于上述原因,我认为这不是一个特别理想的目标。

答案 5 :(得分:0)

我不清楚你想要暴露多少嵌套 类,但如果它们是Document的一部分,它们可能应该是。{1}} 嵌套类。你的意思的例子,在你的开始 代码,正是人们如何在C ++中做到这一点:

class Document
{
public:  //  or not?
    class Header
    {
    };
    class Body
    {
    };
    class Footer
    {
    };
};

关于我能看到的唯一反对意见仅是实施文件 与Document::Header有关的问题必须包括整个Document 类定义,但我不认为这是一个主要问题;如果 Document::Header真的不是独立的,那么它似乎是合理的 需要这个。关于您对此解决方案的第二个异议: 你永远不想让一个对象来自它的部分:Document hasA Header;它不是 isA 的关系。

如果将Header等单独使用确实有意义,那么 最好的解决方案是在Document类之外定义它们 为他们提供更具描述性的名称(例如DocumentHeader)或包装 它们位于特殊的命名空间中(例如namespace DocumentParts)。根据 关于他们与Document的关系,使用它可能是有意义的 typedef中的Document,以便将其称为“{1}} DocumentParts::HeaderDocument::Header