0

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

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

文档{页眉{}正文{}页脚{}}

Document 是一个可以有页眉、正文和页脚的对象。

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

  • 文档
  • 文档::标题
  • 文档::正文
  • 文档::页脚

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

1) 命名空间文档 { ... }

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

2) 命名空间 Document { class ... } typedef Document::Document 文档;

这种情况下给出了 document 和 Document::{part},在区分大小写的情况下,它们可能看起来很奇怪且不相关。

3)类文档{类...};

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

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

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

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

--- 抽象框架 ---

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

- - 观点 - -

整个模块是一个对象的定义。如果能够在没有任何额外的语言嘲笑的情况下使用它,那就太好了。

=== 分辨率 ===

感谢您的反馈意见。

在 C++ 中有一种方法可以将命名空间名称链接到类之前,我想我会使用

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

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

4

6 回答 6

6

Your third option - using nested class declarations / definitions, will get you the ideal scope resolution as you want (though it will not involve a single namespace).

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

    class Body
      {
      // Body class declaration here
      };

   class Footer
      {
      // Footer class declaration here
      };

    // Document declaration here.
  };

Your concerns with that option are:

Requires including Document header in definition of every nested class

Yes - the nested classes are inextricably linked to the surrounding class, their implementations will depend on the definition of the surrounding class because it contains the definitions of the nested classes. This is unavoidable.

Dpesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.

What you are trying to do seems to make very little logical sense - you are trying to define something based on its own parts, which is a circular definition. What are you trying to achieve by deriving Document from Header, Body or Footer?

The final line of your question suggests that you find your desired functionality "trivial", but in my opinion and experience it is far from trivial. You seem to be conflating a namespace and a class because of syntactical similarities, but they are entirely different concepts. You have to separate the two in your mind, they have very little overlap besides some scoping effects and scope resolution syntax. Your "Document" must be either a namespace and a class. Pick one ;) (technically it's actually possible to have both a namespace Document and a class Document, but this is likely to be a source of confusion. )

于 2012-09-25T09:26:20.867 回答
2

您的第一个案例完全符合您的要求。没有什么多余的Document::Document——它指的是命名空间中的DocumentDocument。命名空间中很可能有一个 Document 类,XML命名空间中还有另一个MyCompany

您的第二种情况看起来像是试图从根本上破坏使用名称空间的目的。如果您不想使用命名空间,请不要 - 只需使用全局(未指定)命名空间并冒冲突的风险。如果您只想避免Document::代码中与您的Document类相关的部分,请在该代码中添加using namespace Document指令。

于 2012-09-25T09:29:58.610 回答
1

3)类文档{类...};

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

不,这种设计是最有意义的。我不明白你认为class和之间的区别是什么namespace class

class Document
{
public:
    class Header
    {
    };

    Header m_header;

    class Body
    {
    };

    Body m_Body;
};

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

唯一固有的奇怪之处是您不能将类型和成员变量命名为相同的名称,但是有很多方法可以解决这个问题,这实际上是一个表面上的限制。

于 2012-09-25T09:27:09.683 回答
1

您只需将零件类包含在Document类中。

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

您可以有效地使用它:

Document myDoc;   // Type Document
Document::Header myHeader;
于 2012-09-25T09:27:23.960 回答
1

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

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

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

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

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

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

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

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

于 2012-09-25T09:50:09.853 回答
0

我不完全清楚你想公开多少嵌套类,但如果它们是 的一部分Document,它们可能应该是嵌套类。你的意思的例子,在你的代码的开头,就是在 C++ 中如何做到这一点:

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

关于我能看到的唯一反对意见是,只关心的实现文件Document::Header必须包含整个Document 类定义,但我认为这不是一个大问题;如果 Document::Header真的不是独立的,那么要求这个似乎是合理的。关于你对这个解决方案的第二个反对意见:你永远不想让一个对象从它的部分派生:a Document hasA Header ; 这不是isA关系。

Header如果单独使用 et al确实有意义,那么最好的解决方案是在Document类之外定义它们,或者给它们更多描述性的名称(例如DocumentHeader)或将它们包装在一个特殊的名称空间中(例如namespace DocumentParts)。根据它们与 的关系,使用inDocument可能是有意义的 ,这样它们就可以被称为 or 或。typedefDocumentDocumentParts::HeaderDocument::Header

于 2012-09-25T09:52:59.360 回答