Ответ 1
Взгляните на Qt4, я всегда был его поклонником.
обновила ссылку.
С++ - это язык с несколькими парадигмами и STL и Boost построены по функциональной парадигме языка. STL состоит из контейнеров (для хранения данных), итераторов (для доступа к данным) и алгоритмов (функций для управления данными). Алгоритмные функции применяются к контейнерам с помощью итераторов. В качестве побочного эффекта эти методы не являются частью классов контейнеров, но полностью разделены. (Это позволяет избежать избыточности для библиотек, но это больно для пользователей библиотеки.)
Существуют ли альтернативы С++ для STL/Boost, которые предлагают такие контейнеры в более традиционном объектно-ориентированном вкусе? Я ищу строки, векторы, связанные списки, карту, деревья, хэш-таблицы и т.д. Контейнеры должны быть легко унаследованы и распространены. Для сравнения, расширение классов из STL/Boost - это очень плохая идея, и это по дизайну их дизайнеров.
PS: Пожалуйста, не используйте пространство ответов ниже, чтобы продемонстрировать преимущества STL/Boost. Я им хорошо знаком!: -)
Взгляните на Qt4, я всегда был его поклонником.
обновила ссылку.
Многие (большинство!) старых библиотек для С++ использовали контейнеры, которые были гораздо ближе к тем, которые используются в таких вещах, как Java и С#.
Несколько примеров таких библиотек включают COOL, ET ++, Библиотека классов NIH и Rogue Wave Tools.h ++.
Две точки:
Конечно, я здесь ясен, по крайней мере, ИМО:
Ты сам по себе. Вы были предупреждены!
Закрытые субтитры для ослабленного юмора: конечно, некоторые из них предназначены для юмористики - действительно, действительно паршивая идея, хотя
Это позволяет избежать избыточности для библиотеки писателей, но больно для библиотеки пользователей.
Я не согласен с этой предпосылкой. И даже если бы я это сделал, это огромное чрезмерное обобщение, которое не распространяется на каждого пользователя библиотеки. Но в любом случае это субъективное утверждение, поэтому я проигнорирую его.
Существуют ли альтернативы С++ для STL/Boost, которые предлагают такие контейнеры в более традиционных объектно-ориентированных аромат?
...
Контейнеры должны иметь методы, которые позволять им манипулировать ими непосредственно. (Например, вызов vector.sort() вместо сортировать (vector.begin(), vector.end()).
Конечно. Просто создайте свои собственные контейнеры, которые имеют стандартные контейнеры в качестве элементов данных и делегируют их вызовы и алгоритмы по мере необходимости через функции-члены. Это довольно тривиально:
template<typename T>
class MyVector
{
public:
void sort()
{
std::sort(vec.begin(), vec.end());
}
// ...
private:
std::vector<T> vec;
};
Нет ничего в С++, который мешает вам делать что-то подобное, по иронии судьбы благодаря многопарадигматической природе С++, с которой вы, похоже, не согласны.
Возможно, вы можете использовать объявления private
inheritance и using
, если вы скорее не записываете функции-оболочки.
STL/Boost дают боль для получения из их контейнеров и расширять их.
Это потому, что вы не должны получать от них. Правильный способ - использовать композицию, такую как фрагмент кода, представленный выше.
STL и Boost являются объектно-ориентированными, как вы можете получить.
Во всех теоретических целях функция-член и свободная функция, перегруженная по первому аргументу, - одно и то же. Они действуют очень точно на практике, в том числе и для наследования, поэтому на С++ вы должны действительно рассматривать свободные функции, принимающие (возможно, const) ссылку в качестве первых аргументов как методы их первого аргумента.
Преимущество бесплатных функций заключается в том, что они могут быть определены для существующего класса, что позволяет вам добавить интерфейс к существующему классу. Именно поэтому STL и особенно boost используют их так много. Главное преимущество функций-членов - они могут быть виртуальными (но виртуальные методы должны быть приватными в любом случае!)
Вы не хотите расширять коллекции деривацией. Как правило, вы не хотите расширять что-либо путем деривации, если только он не является абстрактным базовым классом, специально разработанным для него. См. этот вопрос о преимуществах композиции над наследованием.
Ты идешь не так. Если вы хотите запрограммировать в Java, то программа на Java. Если вы программируете на С++, тогда программируйте как программисты на С++. Всегда плавайте с течением, никогда против него.
Почему бы не использовать граф вместо контейнеров STL и прикрепить то, что вам нужно на узлах или краях. Они могут имитировать любые контейнеры STL (я не прав?). Вы можете легко перебирать узлы или ребра (DFS, BFS) и по тому, как вы можете делать то, что вам нравится, с данными, прикрепленными к узлам и краям. Легкое сочетание алгоритма и итератора, не так ли?
Что сказал Дилавар, на самом деле является решением для всех ваших потребностей в контейнере.
Используйте Boost:: graph или аналогичную реализацию. Вы можете использовать его [это то, что я делаю] как систему управления объектами.
Что касается критики STL, это просто вопрос вкуса, а не технические возражения. Они существуют, но не на этом уровне.
Придя немного опаздывать на эту вечеринку И я знаю, что OP специально просит не "понтификатировать", как они уже знают о STL, однако...
Существует старый Dr. Dobbs с Алексом Степановым, пионером в разработке общих программ и основным спонсором STL. Очень поучительно несколько способов, особенно для решения вопроса о том, почему в STL не используются более стандартные методы OO. Один абзац выделяется:
Даже сейчас наследование С++ не очень полезно для общего программирования. Давайте обсудим, почему. Многие люди пытались использовать наследование для реализации структур данных и классов контейнеров. Как мы знаем сейчас, было мало успешных попыток. Наследование С++, а связанный с ним стиль программирования резко ограничен. Невозможно реализовать дизайн, который включает в себя тривиальную вещь, как использование равенства. Если вы начинаете с базового класса X в корне вашей иерархии и определяете оператор виртуального равенства в этом классе, который принимает аргумент типа X, то выведите класс Y из класса X. Каков интерфейс равенства? Он имеет равенство, которое сравнивает Y с X. Используя животных в качестве примера (люди ОО любят животных), определите млекопитающих и выведите жирафа у млекопитающих. Затем определите член-функцию-член, где животные согласуются с животными и возвращают животное. Затем вы получаете жирафа от животного и, конечно же, у него есть помощник по функциям, где жираф соединяется с животным и возвращает животное. Это определенно не то, что вы хотите. Хотя спаривание может быть не очень важно для программистов на C++, равенство есть. Я не знаю ни одного алгоритма, где не используется какое-либо равенство.
Для тех, кто предпочитает ответ Java на эту же загадку, Джош Блох прилагает все усилия, чтобы сделать те же самые пункты в Эффективной Java, Пункт 8: Послушать общий контакт при переопределении.
Это хорошая глава, с хорошим примером о попытке сохранить равный контракт, в то же время расширяя простой класс Point и добавленный цвет: класс ColorPoint. Он продолжает демонстрировать, что существует фундаментальное ограничение ООП: нет возможности расширить экземпляр класса и добавить компонент значения при сохранении равного контракта.
Конечно, высказывание Блоха более кратко изложено, но они оба (правильно) делают одни и те же выводы. Основное отличие состоит в том, что Java является (является) языком "чистого OO" - все должно находиться в классе, даже такие вещи, как алгоритмы, которые не являются естественными объектами.
И я думаю, что Блох может быть чувствительным к этой проблеме, потому что он видел, что он не впечатляет в библиотеке Java: Stack, наследующий от Vector, является одним из примеров заметной проблемы проектирования в Java.
Чуть позже в интервью Степанов продолжает:
Я участвовал в нескольких дискуссиях на раннем этапе в Bell Labs о разработке шаблонов и довольно жестоко спорил с Bjarne о том, что он должен сделать шаблоны С++ максимально приближенными к дженерикам Ada. Я думаю, что я так сильно рассуждал, что он решил против этого. Я осознал важность наличия функций шаблона на С++, а не только классов шаблонов, как полагали некоторые люди. Я думал, однако, что функции шаблонов должны работать как генераторы Ada, то есть они должны быть явно созданы. Бьярне не слушал меня, и он разработал механизм функций шаблона, где шаблоны создаются неявно с использованием механизма перегрузки. Эта особая техника стала решающей для моей работы, потому что я обнаружил, что это позволило мне сделать много вещей, которые не были возможны в Аде. Я рассматриваю этот конкретный проект Бьярне как замечательный труд, и я очень рад, что он не последовал моему совету.