Должен ли я использовать вложенные классы в этом случае? - PullRequest
48 голосов
/ 02 августа 2008

Я работаю над коллекцией классов, используемых для воспроизведения и записи видео. У меня есть один основной класс, который действует как открытый интерфейс, с такими методами, как play(), stop(), pause(), record() и т. Д. Затем у меня есть классы рабочих лошадей, которые выполняют декодирование видео и кодирование видео.

Я только что узнал о существовании вложенных классов в C ++, и мне любопытно узнать, что программисты думают об их использовании. Я немного осторожен и не совсем уверен, какие преимущества / недостатки есть, но они (в соответствии с книгой, которую я читаю), похоже, используются в таких случаях, как мой.

Книга предполагает, что в таком сценарии, как мой, хорошим решением было бы вложить классы рабочей лошадки в класс интерфейса, чтобы не было отдельных файлов для классов, которые клиент не должен использовать, и чтобы избежать возможных имен конфликты? Я не знаю об этих оправданиях. Вложенные классы - это новая концепция для меня. Просто хочу посмотреть, что программисты думают об этой проблеме.

Ответы [ 10 ]

25 голосов
/ 02 августа 2008

Я бы неохотно использовал здесь вложенные классы. Что, если вы создали абстрактный базовый класс для «драйвера мультимедиа» для обработки серверной части (рабочей лошадки) и отдельный класс для внешней работы? Интерфейсный класс может принимать указатель / ссылку на реализованный класс драйвера (для соответствующего типа носителя и ситуации) и выполнять абстрактные операции над структурой рабочей лошадки.

Моя философия заключается в том, чтобы пойти дальше и сделать обе структуры доступными для клиента безупречным образом, только при условии, что они будут использоваться в тандеме.

Я бы сослался на что-то вроде QTextDocument в Qt. Вы предоставляете прямой интерфейс для обработки данных с нуля, но передаете полномочия объекту, подобному QTextEdit, для выполнения манипуляций.

9 голосов
/ 17 сентября 2008

Вы бы использовали вложенный класс, чтобы создать (маленький) вспомогательный класс, необходимый для реализации основного класса. Или, например, определить интерфейс (класс с абстрактными методами).

В этом случае основным недостатком вложенных классов является то, что это затрудняет их повторное использование. Возможно, вы захотите использовать свой класс VideoDecoder в другом проекте. Если вы сделаете это вложенным классом VideoPlayer, вы не сможете сделать это элегантным способом.

Вместо этого поместите другие классы в отдельные файлы .h / .cpp, которые затем можно использовать в своем классе VideoPlayer. Клиенту VideoPlayer теперь нужно только включить файл, который объявляет VideoPlayer, и все же не нужно знать, как вы его реализовали.

5 голосов
/ 05 августа 2008

Один из способов решить, использовать ли вложенные классы или нет, - подумать, играет ли этот класс вспомогательную роль или свою роль.

Если он существует исключительно для помощи другому классу, я обычно делаю его вложенным. В этом есть целый ряд предостережений, некоторые из которых кажутся противоречивыми, но все сводится к опыту и интуиции.

4 голосов
/ 26 сентября 2008

Что ж, если вы используете указатели на ваши классы рабочих лошадей в вашем классе Interface и не выставляете их как параметры или возвращаемые типы в ваших интерфейсных методах, вам не нужно будет включать определения этих рабочих лошадей в заголовочный файл вашего интерфейса. (вы просто вперед, чтобы объявить их). Таким образом, пользователям вашего интерфейса не нужно будет знать о классах в фоновом режиме.

Тебе определенно не нужно вкладывать классы для этого. Фактически, отдельные файлы классов на самом деле сделают ваш код более читабельным и простым в управлении по мере роста вашего проекта. это также поможет вам позже, если вам нужно создать подкласс (например, для разных типов контента / кодеков).

Подробнее о шаблоне PIMPL (раздел 3.1.1).

4 голосов
/ 21 сентября 2008

Мы столкнулись с проблемой полустарелого компилятора Sun C ++ и видимости вложенных классов, поведение которых изменилось в стандарте. Конечно, это не повод отказываться от вложенного класса, просто нужно помнить об этом, если вы планируете компилировать свое программное обеспечение на многих платформах, включая старые компиляторы.

4 голосов
/ 16 сентября 2008

Иногда целесообразно скрыть классы реализации от пользователя - в этих случаях лучше поместить их в файл foo_internal.h, чем в определение открытого класса. Таким образом, читатели вашего foo.h не увидят того, с чем вы бы предпочли, они не будут обеспокоены, но вы все равно сможете написать тесты для каждой конкретной реализации вашего интерфейса.

4 голосов
/ 05 августа 2008

звучит как случай, когда вы можете использовать шаблон стратегии

2 голосов
/ 18 сентября 2008

Вы должны использовать внутренний класс только тогда, когда вы не можете реализовать его как отдельный класс, используя открытый интерфейс потенциального внешнего класса. Внутренние классы увеличивают размер, сложность и ответственность класса, поэтому их следует использовать экономно.

Ваш класс кодировщика / декодера звучит так, как будто он лучше соответствует паттерну стратегии

1 голос
/ 23 сентября 2008

Еще одна вещь, о которой нужно помнить, это то, представляете ли вы когда-нибудь разные реализации своих рабочих функций (например, декодирование и кодирование). В этом случае вам определенно понадобится абстрактный базовый класс с различными конкретными классами, которые реализуют функции. На самом деле было бы неуместно вкладывать отдельный подкласс для каждого типа реализации.

1 голос
/ 20 сентября 2008

Одна из причин, по которой следует избегать вложенных классов, заключается в том, что если вы когда-нибудь намереваетесь обернуть код swig (http://www.swig.org) для использования с другими языками. В настоящее время Swig испытывает проблемы с вложенными классами, поэтому взаимодействует с библиотеками, которые предоставляют любые вложенные классы. становится настоящей болью.

...