Почему C++11 строковые новые функции (stod, stof) не являются функциями-членами строкового класса?

Почему эти C++11 новые функции заголовка <string> (stod, stof, stoull) не является членом функции string учебный класс?

Не более совместим с C++ для написания mystring.stod(...) скорее, чем stod(mystring,...)?

3 ответа

Решение

Это удивляет многих, но C++ не является объектно-ориентированным языком (в отличие от Java или C#).

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

Рекомендация: отдавать предпочтение функциям, не являющимся членами, а не функциям-членам (из Efficient C++, пункт 23)

Причина: функция-член или функция-друг имеет доступ к внутренним объектам класса, тогда как функция, не являющаяся членом-другом, не имеет доступа; поэтому использование функции, не являющейся членом-другом, увеличивает инкапсуляцию.

Исключение: когда функция-член или функция-друг обеспечивает значительное преимущество (например, производительность), тогда стоит задуматься, несмотря на дополнительную связь. Например, даже если std::find работает очень хорошо, ассоциативные контейнеры, такие как std::set обеспечить функцию-член std::set::find который работает в O(log N) вместо O(N).

Основная причина в том, что они не принадлежат там. Они на самом деле не имеют ничего общего со строками. Остановись и подумай об этом. Пользовательские типы должны следовать тем же правилам, что и встроенные типы, поэтому каждый раз, когда вы определяете новый пользовательский тип, вам необходимо добавить функцию в std::string, На самом деле это было бы возможно в C++: если std::string имел шаблон функции-члена to без общей реализации вы можете добавить специализацию для каждого типа и вызвать str.to<double>() или же str.to<MyType>(), Но действительно ли это то, что вы хотите. Для меня это не кажется чистым решением, когда все пишут новый класс, добавляя специализацию к std::string, Помещение подобных вещей в строковый класс убивает его и на самом деле является противоположностью того, что ОО пытается достичь.

Если вы будете настаивать на чистой ОО, они должны быть членами double, int и т. д. (действительно, конструктор. Это то, что делает, например, Python.) C++ не настаивает на чистой ОО и не допускает базовые типы, такие как double а также int иметь членов или специальных конструкторов. Таким образом, свободные функции являются приемлемым решением и единственным чистым решением, возможным в контексте языка.

FWIW: преобразование в / из текстового представления - всегда деликатная проблема: если я делаю это в целевом типе, то я ввел зависимость от различных источников и приемников текста в целевом типе - и они могут варьироваться время. Если я делаю это в типе источника или приемника, я делаю их зависимыми от конвертируемого типа, что еще хуже. Решение C++ состоит в том, чтобы определить протокол (в std::streambuf), где пользователь пишет новую бесплатную функцию (operator<< а также operator>>) для обработки преобразований и рассчитывает на разрешение перегрузки оператора, чтобы найти правильную функцию. Преимущество решения с бесплатной функцией заключается в том, что преобразования не являются частью ни типа данных (который не должен знать об источниках и приемниках), ни типа источника или приемника (который, таким образом, не должен знать о пользовательских типы данных). Это кажется лучшим решением для меня. И функции как stod это просто удобные функции, которые облегчают написание одного частого использования.

На самом деле это некоторые служебные функции, и они не должны находиться внутри основного класса. Подобные служебные функции, такие как atoi, atof определены (но для char*) внутри stdlib.h, и они тоже являются автономными функциями.

Другие вопросы по тегам