Подтвердить что ты не робот

Стандартная практика С++: классы виртуального интерфейса и шаблоны

Я должен принять решение относительно обобщения и полиморфизма.

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

Я буду вводить чисто виртуальные базовые классы (интерфейсы) или шаблоны?

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

stl не использует много (или нет?) наследования, а boost тоже не работает. Но я думаю, что они нацелены на то, чтобы быть очень маленькими базовыми инструментами, которые используются каждый 2 строки кода программистом.

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

Ну, мой сценарий в некоторой степени заключен между собой.

Мне не нужно обмениваться кусочками кода "на лету" во время выполнения, время компиляции в порядке. Обычно это также очень центральная и часто используемая функциональность, он не логически разделяется на большие блоки.

Это позволяет мне несколько придать шаблонному решению. Для меня это также выглядит несколько чище.

Есть ли какие-то большие плохие последствия, все еще интерфейсы идти? Когда они не? Что больше соответствует стандарту С++?

Я знаю, что это граничит с субъективным, но меня действительно интересует некоторый опыт. У меня нет копии Скотта Мейера, эффективного С++ поэтому я возлагаю надежды на вас, ребята:)

4b9b3361

Ответ 1

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

Единственным возможным недостатком шаблонов является то, что 1) они обычно должны быть определены в заголовках (что означает, что больше кода получает #include), и это часто приводит к более медленному времени компиляции.

Но конструктивно, я не вижу никаких проблем с использованием шаблонов, когда это возможно.

Что больше соответствует стандарту С++ стиль?

Зависит от того, что такое "стандартный стиль С++". Стандартная библиотека С++ использует немного всего. STL использует шаблоны для всего, немного более старая библиотека IOStreams использует наследование и виртуальные функции, а функции библиотеки, унаследованные от C, не используют, конечно.

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

Ответ 2

Свойства классического объектно-ориентированного полиморфизма:

  • объекты привязаны во время выполнения; это более гибко, но также потребляет больше ресурсов (ЦП) во время выполнения
  • сильная типизация привносит несколько более безопасный тип, но необходимость dynamic_cast (и его возможность взорвать лицо клиента) может легко компенсировать это.
  • вероятно, более широко известны и поняты, но "классические" иерархии глубокого наследования кажутся мне ужасающими.

Свойства полиморфизма времени компиляции по шаблону:

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

Обратите внимание, что нет необходимости принимать решение для одного. Вы можете свободно смешивать и смешивать их обоих (и многие другие идиомы и парадигмы). Часто это приводит к очень внушительному (и выразительному) коду. (См., Например, такие вещи, как стирание стилей.) Чтобы понять, что возможно благодаря умному смешиванию парадигм, вы можете просмотреть Alexandrescu "Modern С++ Design".

Ответ 3

Это что-то вроде ложной оппозиции. Да, основное использование наследования и виртуальных функций находится в iostreams, которые очень старые и написаны в совершенно другом стиле для остальных библиотек std.

Но многие из самых "классных" современных библиотек С++, таких как boost, используют полиморфизм во время выполнения, они просто используют шаблоны, чтобы сделать его более удобным для использования.

boost::any и std::tr1::function (ранее также из boost) являются прекрасными примерами.

Они представляют собой контейнеры с одним элементом для чего-то, чей конкретный тип неизвестен во время компиляции (это особенно заметно при использовании any, потому что у него есть свой собственный динамический оператор-оператор, чтобы получить значение).

Ответ 4

После того, как вы перекусили немного больше опыта на моей тарелке, в шаблонах, которые мне не нравятся, есть некоторые вещи: Существуют определенные недостатки, которые дисквалифицируют метапрограммирование шаблона как пригодный для использования язык:

  • читаемость: слишком много скобок, слишком много неязыковых принудительных (поэтому неправильно используемых) соглашений
  • для тех, кто проходит обычную эволюцию в языках программирования, шаблоны нечитабельны и непонятны (просто посмотрите на boost bgl)
  • Иногда кажется, что кто-то пытался написать генератор кода С++ в awk.
  • сообщения об ошибках компилятора - cl (utter) ed crap
  • слишком много необходимых хаков (большинство из них исправлено в С++ 0x), чтобы получить базовые "языковые" функции.
  • Нет шаблонов в файлах реализации, в результате чего в библиотеках только заголовка (который является очень двухсторонним мечом)
  • обычные функции завершения кода IDE не очень помогают шаблонам.
  • Выполнение большого материала в MPL кажется "худшим", не может найти для него другого слова. Каждая строка шаблонного кода создает ограничения на этот тип шаблона, которые принудительно применяются в способе замены текста. Есть семантика, присущая иерархиям наследования, в структурах шаблонов нет. Он, как и все, является void *, и компилятор пытается сказать вам, будет ли segfault.

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

Ответ 5

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

Оба метода имеют несколько эквивалентных шаблонов, которые означают для многих вещей, которые вы можете использовать. EG Strategy in OO vs Policy in Generics или Template Method в OO по сравнению с обычным повторяющимся шаблоном шаблона в дженериках.

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

Лично я лучше в OO и, как правило, предпочитаю его, поскольку я знаю, что могу создавать чистые проекты, которые легко понять и что большинство людей может изменить. Самый общий код, который я правильно, нацелен на взаимодействие с другим общим кодом, например, с написанием итератора или общей функцией для алгоритмов.

Ответ 6

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