Возможный дубликат:
Плюсы и минусы использования вложенных классов C ++ и перечислений?
Рассмотрим следующую декларацию.
class A {
public:
class B{
};
};
Ничего особенного.
Что Вы думаете об этом?
Концептуально, это позволяет программисту (ам) знать, что класс B относится конкретно к классу A. Когда вы используете класс B вне класса A, вы должны использовать тип как A :: B, который каждый раз напоминает вам, что B является относится к А. Это не добавляет никакой функциональности, но показывает отношения.
Точно так же вам совсем не нужно использовать наследование / композицию или классы. Вы можете более или менее моделировать классы в C, просто используя структуры и функции. Это просто способ сделать код чище и понятнее, а программисту проще связать код с дизайном. Классы достигают этого гораздо больше, чем публичные подклассы, но это только пример.
Если это закрытый / защищенный подкласс (который, как я вижу, не в вашем примере), то это, очевидно, ограничивает этот класс реализацией этого класса и дочерних элементов этого класса, что может быть желательным (опять же в отношении дизайна), если только Вариант использования этого класса находится в реализации этого класса (и, возможно, его дочерних элементов).
Преимущество 1: аспект пространства имен
В самом деле, A
обеспечивает пространство имен для B
и это может помочь нам структурировать наш код намного лучше. Рассмотрим конкретный пример с vector
за A
, а также iterator
за B
, Можно утверждать, что
class vector {
public:
class iterator { /*...*/ };
iterator begin() { /*...*/ }
};
легче набирать, читать и понимать, чем
class vector_iterator {
/*...*/
};
class vector {
public:
vector_iterator begin() { /*...*/ }
};
Соблюдайте, в частности:
Когда два класса (vector
а также iterator
) зависят друг от друга, т. е. используют члены друг друга, вторая версия выше потребует, чтобы одно из двух было объявлено заранее, а в некоторых случаях взаимные зависимости типов могут привести к неразрешимым ситуациям. (Используя вложенные классы, намного легче избежать таких проблем, потому что в большинстве частей определения вложенного класса рассматривается внешний класс полностью определены. Это связано с §9.2 / 2.)
У вас вполне может быть много других типов данных, которые поддерживают свои собственные iterator
например, linked_list
, Используя вторую версию выше, вам нужно определить linked_list_iterator
как отдельный класс. Имена классов будут становиться все длиннее и сложнее, чем больше добавленных вами «зависимых» типов и альтернативных типов.
Преимущество 2: шаблоны
Продолжая приведенный выше пример, рассмотрим теперь шаблон функции, который принимает контейнер (например, vector
а также linked_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
Тип должен быть в состоянии использоваться вне класса контейнера.
Какие причины могут быть для помещения одного класса в другой?
inner class declaration
, Проверь это ссылка на сайт.