2

我正在构建一个类(A类),它需要能够在其操作过程中创建另一个类(B类)的多个实例,但B类仅由A类的少数成员函数使用,并且从未在课堂外使用过。如何最好地定义 B 类?使其成为 A 类的私人成员是否可行/合理?这是嵌套类的预期目的,还是我放弃了构造的精神?

谢谢,怀亚特

编辑:进一步考虑,我并没有真正询问最佳实践,因为这是针对个人项目的。从封装的角度来看,我想将 B 类包含为 A 类的成员——完全从属的类实际上应该是其所属类的一部分,这似乎是合理的。

我想知道这是否是嵌套类的合理用例?如果不是,嵌套类的目的是什么?

4

6 回答 6

3

一种detail可能性是在放置类的名称空间内定义一个名称空间。例如

// public_namespace_detail.hpp
namespace public_namespace
{
    namespace detail
    {
        class B
        {
          ...
        };

    }
}

// public_namespace.hpp
#include "public_namespace_detail.hpp"

namespace public_namespace
{
    class A
    {
       detail::B b;
       ...       
    };
}
于 2010-12-20T15:52:00.587 回答
2

我只想class B完全无关class A——如果没有别的,如果你可以单独测试,它将更容易编写class A测试class B。如果您不想走那条路,请阻止任何人实例化,class B除非class A定义class B,使其具有私有构造函数,然后class A创建friend.

于 2010-12-20T15:48:10.527 回答
1

您有多种选择:

  1. 私有继承:class A : private B {};

  2. 嵌套类:class A { class B { /* etc */ }; };

  3. A类到B类的好 ol' 私人成员:class A { B b; };

如果您 100% 确定在外部不需要嵌套类,我个人会选择嵌套类。

于 2010-12-20T15:51:28.347 回答
0

对我来说,一般的经验法则是,如果我发现继承存在难题,那么我可能以错误的方式看待问题。

有没有一种方法可以重组你的程序,从而减少类的“耦合”?IE 你能把引用类 B 的函数移出类 A(并将它们放在 B 中)吗?

于 2010-12-20T15:48:50.537 回答
0

我会将它移到 B 之外,否则它将通过 A 的头文件暴露给其他类(无论你喜欢与否)。换句话说,如果您更改 B 的实现,则 A 的客户端必须重新编译 - 因为 B 是在 A 内部声明的。

我的项目结构应该清楚地表明 B 的头文件不应该被其他类使用。例如,我有一个名为“exports”的文件夹,其中放置了我打算在项目外部共享的所有头文件。显然B的标题不会在那里找到。

在另一种不使用头文件的语言中,例如 C#,如果 B 相当小,我会随便将 B 放在 A 中 - 可能不超过 6-10 行声明。

于 2010-12-20T15:58:48.173 回答
0

是的,嵌套类在这里很好。

请注意,为了保持代码井井有条,我不会将 inside 的定义B放在里面A。反而:

class A
{
    class B;
};

class A::B
{
};

除其他外,这允许将类的定义A::B放在 A 的实现文件中。

编辑:由于嵌套类是否可以访问包含类的私有成员似乎有些混淆,我提供了一个代码片段来证明它确实如此:

class A
{
    int x;

    class B
    {
        int func(A* p) { return p->x; }
    };
};

没有内联定义的变体A::B,也被接受:

class A
{
    int x;

    class B;
};

class A::B
{
    int func(A* p) { return p->x; }
};
  • Comeau:接受(两种变体)

您的 Comeau C/C++ 测试结果如下:

用于 ONLINE_EVALUATION_BETA2 的 Comeau C/C++ 4.3.10.1(2008 年 10 月 6 日 11:28:09) 版权所有 1988-2008 Comeau Computing。版权所有。模式:严格错误 C++ noC++0x_extensions

在严格模式下,使用 -tused,编译成功(但请记住,Comeau 在线编译器不会链接)。使用 C++0x 扩展编译已禁用。

于 2010-12-20T16:26:31.357 回答