内部班级声明

Internal class declaration

本文关键字:声明 内部      更新时间:2023-10-16

可能的重复:
使用嵌套C 类和枚举的优点?

考虑以下声明。

class A {
    public:
    class B{
    };
};

没什么特别的。

  • 但是,这有什么好处?
  • 有什么原因将一个班级放在另一个班级?
  • 两个类之间没有继承好处。
  • 如果将b放置在A内部用于其私人名称共享,则A仅适用于B的名称空间,并且也有理由将B私有化。

您对此有何看法?

概念上,它使程序员知道B类专门与A类A相关。,这使您每次B都与A有关。这不会添加任何功能,而是显示一个关系。

类似地,您不必使用继承/构图或类别。您只能通过使用结构和功能或多或少地模拟C中的类。这只是保持代码清洁程序和更简单的一种方法,并让程序员更轻松地将代码与设计联系起来。课程比公共子类所能完成的事情要多得多,但这只是一个例子。

如果它是一个私人/受保护的子类(我认为这不是您的示例),那么显然将该班级限制在该班级的实现和该班级的孩子的实现中,这可能是必需的(再次在设计方面)如果该类的唯一用例是在该类的实施中(可能是其子女)。

好处1:名称空间方面

的确,AB提供了一个名称空间,这可以帮助我们更好地构建代码。考虑使用Avector的具体示例,而Biterator。可以说,

class vector {
public:
  class iterator { /*...*/ };
  iterator begin() { /*...*/ }
};

更容易键入,阅读和理解
class vector_iterator {
  /*...*/
};
class vector {
public:
  vector_iterator begin() { /*...*/ }
};

特别观察:

  1. 当两个类(vectoriterator)相互依赖时,即使用彼此的成员时,上面的第二个版本将要求两个版本中的一个要向前证明,在某些情况下,相互依赖性依赖性可能导致无法解决的情况。(使用嵌套类,避免此类问题要容易得多,因为在嵌套类定义的大多数部分中,外部类被视为完全定义的。这是由于§9.2/2。)。

  2. 您很可能有许多其他数据类型可以维护自己的iterator,例如linked_list。使用上面的第二版,您需要将linked_list_iterator定义为单独的类。班级名称将变得更长且复杂,您添加的这些"相关"类型和替代类型都会变得更加复杂。

好处2:模板

继续上面的示例,现在考虑一个函数模板,该模板将容器(例如上面定义的vectorlinked_list)作为参数,并在其上进行迭代:

template <typename Container>
void iterate(const Container &container) {
  /*...*/
}

在此功能中,您显然非常喜欢使用Container的迭代器类型。如果那是嵌套类型,很容易:

typename Container::iterator

但是,如果不是,则必须将迭代类型作为单独的模板参数:

template <typename Container, typename Iterator>
void iterate(const Container &container) {
  /*...*/
  Iterator it = container.begin();
  /*...*/
}

,如果该迭代器类型没有出现在函数参数之间,则编译器甚至无法猜测该类型。每次调用iterate函数时,您都必须明确添加角度括号。

最终注释:这与嵌套类是公共还是私人的无关。我上面的示例表明,公共嵌套类型显然可以优选的情况,因为我认为iterator类型应该能够在容器类外面使用。

将一个班级放在另一个类中可能是什么原因?

  • 如果您需要将B的范围限制为仅适用于A,则内部类别的定义会有所帮助。因为它将类范围限制为local。这是呼叫范围本地化。这些词在更通用的术语中称为 inner class declaration。检查此链接。
  • 这个stackoverflow问题可帮助您更多地了解。