Мне нужны некоторые мнения гуру C++ о расширяющемся станд.:: строка

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

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

Только что я придумал следующее:

class StringBox
{
public:
   StringBox( std::string& storage ) :
       _storage( storage )
   {
   }

   // Methods I wish std::string had...
   void Format(); 
   void Split();
   double ToDouble(); 
   void Join(); // etc...

private:
  StringBox();

  std::string& _storage;
};

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

Пример использования мог бы быть похожим на это:

string OperateOnString( float num, string a, string b )
{
    string nameS;
    StringBox name( nameS );

    name.Format( "%f-%s-%s", num, a.c_str(), b.c_str() );

    return nameS;
}

Мой вопрос: Что делает гуру C++ сообщества StackOverflow думает об этом методе расширения STL?

7
задан dicroce 10 January 2010 в 17:50
поделиться

6 ответов

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

16
ответ дан 6 December 2019 в 05:06
поделиться

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

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

Следуйте рекомендациям, они есть не просто так :)

.
0
ответ дан 6 December 2019 в 05:06
поделиться

Если область видимости строки не совпадает с StringBox, то можно получить segfaults:

StringBox foo() {
  string s("abc");
  return StringBox(s);
}

По крайней мере, предотвратить копирование объекта, объявив оператор присваивания и скопировав ctor private:

class StringBox {
  //...
  private:
    void operator=(const StringBox&);
    StringBox(const StringBox&);
};

EDIT: относительно API, чтобы не было сюрпризов, я бы заставил StringBox владеть своей копией строки. Могу подумать, что это можно сделать двумя способами:

  1. Скопировать строку в член (не по ссылке), получить результат позже - также в виде копии
  2. Доступ к строке через умный указатель с подсчётом ссылок вроде std::tr1::shared_ptr или boost: shared_ptr, для предотвращения дополнительного копирования
1
ответ дан 6 December 2019 в 05:06
поделиться

Лучший способ - использовать функции без шаблонов. Следующим лучшим вариантом является наследование private struct extended_str : private string, что в C++0x, кстати, проще, чем в , используя конструкторы. Частное наследование - это слишком много хлопот и слишком рискованно просто для добавления некоторых алгоритмов. То, что Вы делаете, слишком рискованно.

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

0
ответ дан 6 December 2019 в 05:06
поделиться

Я добавлю немного чего-то, что еще не было опубликовано. Библиотека библиотеки алгоритмов строки приняла бесплатный функциональный подход шаблона, а строковые алгоритмы, которые они обеспечивают, впечатляют повторно использовать для всего, что выглядит как строка: std :: string, char *, std :: вектор , итераторы пары ... Вы называете это! И они кладут их все аккуратно в пространстве имен Boost :: Algorithm (я часто использую с использованием Algo Pespace Algo = Boost :: Algorithm , чтобы создать код манипуляции с строкой).

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

Для безопасного форматирования стиля стилей печати проверьте Boost.Format . Это может выводить на строки и потоки.

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

2
ответ дан 6 December 2019 в 05:06
поделиться

Я никогда не был взволнован этим решением. Для одного не обязательно очевидно, где все такие методы в коде, для другого, мне просто не нравится синтаксис. Я хочу использовать. Когда я называю методы!

И я хочу использовать $! --- & Когда я звоню методы! Смирись с этим. Если вы собираетесь написать код C ++, придерживайтесь конвенций C ++. И очень важная конвенция C ++ - предпочтить функции, не являющиеся членами, когда это возможно.

Существует причина, причина C ++ GUURUS рекомендует это:

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

лично, я не вижу точки в вашем коде. Разве это не намного проще, более читаемо и короче?

string OperateOnString( float num, string a, string b )
{
    string nameS;
    Format(nameS, "%f-%s-%s", num, a.c_str(), b.c_str() );
    return nameS;
}

// or even better, if `Format` is made to return the string it creates, instead of taking it as a parameter
string OperateOnString( float num, string a, string b )
{
    return Format("%f-%s-%s", num, a.c_str(), b.c_str() );
}

Когда в Риме, делайте как римляне, как говорится. Особенно Когда римляне имеют веские причины делать, как они. И особенно когда ваш собственствует способ выполнения этого, на самом деле не имеет одного преимущества. Более подвержено ошибкам, запутавшим людям, чтению вашего кода, неидиомата, и это просто больше строк кода, чтобы сделать то же самое.

Что касается вашей проблемы, что трудно найти функции не-члена, которые расширяют строку , поместите их в пространство имен, если это проблема. Это то, что они для. Создайте пространство имен StringUtil или что-то, и поставьте их туда.

19
ответ дан 6 December 2019 в 05:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: