2008-08-02 4 views
40

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

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

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

ответ

24

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

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

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

4

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

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

3

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

8

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

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

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

1

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

Вашего кодер класс/декодер кажется, что лучше подходят Strategy Pattern

0

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

3

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

0

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

4

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

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

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

Смежные вопросы