Вопрос « Куда мне помещать функции, не связанные с классом », вызвал некоторые споры о том, имеет ли смысл в C ++ объединять служебные функции в классе или они просто существуют как свободные функции в пространстве имен.
Я пришел из C # фона, где последний вариант не существует, и, таким образом, естественным образом склоняется к использованию статических классов в небольшом коде C ++, который я пишу. Ответ на этот вопрос, получивший наибольшее количество голосов, а также несколько комментариев, однако, говорят, что предпочтение отдается свободным функциям, даже если предположить, что статические классы были анти-паттерном. Почему это так в C ++? По крайней мере, на первый взгляд статические методы класса кажутся неотличимыми от свободных функций в пространстве имен. Почему при этом предпочтение отдается последнему?
Изменится ли ситуация, если для набора служебных функций потребуются некоторые общие данные, например, кэш, который можно хранить в частном статическом поле?
источник
Ответы:
Я предполагаю ответить, что мы должны сравнить намерения как классов, так и пространств имен. Согласно Википедии:
Учебный класс
Пространство имен
Теперь, чего вы пытаетесь достичь, помещая функции в класс (статически) или в пространство имен? Держу пари, что определение пространства имен лучше описывает ваше намерение - все, что вам нужно, это контейнер для ваших функций. Вам не нужны какие-либо функции, описанные в определении класса. Обратите внимание, что первые слова определения класса - « В объектно-ориентированном программировании », но в коллекции функций нет ничего объектно-ориентированного.
Вероятно, есть и технические причины, но, как кто-то из Java и пытается осмыслить мультипарадигмальный язык C ++, наиболее очевидный ответ для меня таков: потому что для этого не требуется ОО.
источник
Я бы очень осторожно назвал это анти-паттерном. Пространства имен обычно предпочтительнее, но, поскольку нет шаблонов пространства имен, и пространства имен не могут быть переданы в качестве параметров шаблона, использование классов, не имеющих ничего, кроме статических членов, является довольно распространенным явлением.
источник
В тот день мне нужно было учиться на Фортране. К тому времени я знал другие императивные языки, поэтому решил, что смогу изучать фортран без особого изучения. Когда я сдал свою первую домашнюю работу, профессор вернул ее мне и попросил повторить ее: он сказал, что программы на языке Pascal, написанные в синтаксисе FORTRAN, не считаются действительными представлениями.
Схожая проблема здесь: использование статических классов для размещения служебных функций в C ++ - это идиома для C ++.
Как вы упомянули в своем вопросе, использование статических классов для служебных функций в C # является необходимостью: автономные функции просто недоступны в C #. Язык, необходимый для разработки шаблона, позволяющего программистам определять автономные функции другим способом, а именно - внутри статических служебных классов. Это был уловка Java, взятая дословно: например, java.lang.Math и System.Math .NET почти изоморфны.
C ++, однако, предлагает пространства имен, другое средство для достижения той же цели, и он активно использует его в реализации своей стандартной библиотеки. Добавление дополнительного слоя статических классов не только не нужно, но и несколько нелогично для читателей без C # или фона Java. В некотором смысле вы вводите «перевод ссуды» на язык для чего-то, что может быть выражено естественным образом.
Когда ваши функции должны обмениваться данными, ситуация другая. Поскольку ваши функции больше не связаны , шаблон Singleton становится предпочтительным способом удовлетворения этого требования.
источник
Возможно, вам нужно спросить, почему вы хотите полностью статический класс?
Единственная причина, по которой я могу придумать, заключается в том, что другие языки (Java и C #), которые очень «все являются классом», требуют их. Эти языки вообще не могут создавать функции верхнего уровня, поэтому они придумали хитрость для их сохранения, и это была статическая функция-член. Это немного обходной путь, но C ++ не нуждается в таком, вы можете напрямую создавать совершенно новые независимые функции верхнего уровня.
Если вам нужны функции, которые работают с конкретным элементом данных, то имеет смысл объединить их в класс, содержащий данные, но затем они перестают быть функциями и начинают быть членами этого класса, которые работают с данными класса.
Если у вас есть функция, которая не работает с определенным типом данных (я использую слово здесь, поскольку классы - это способы определения новых типов данных), тогда это действительно анти-шаблон, который не позволяет им помещать их в класс, иначе как семантические цели.
источник
Другими словами, наличие класса вместо пространства имен не имеет преимуществ.
Во-первых, это экономит ваше время при наборе текста
static
, хотя это, пожалуй, довольно незначительное преимущество.Основным преимуществом является то, что это наименее мощный инструмент для работы. Классы могут использоваться для создания объектов, они могут использоваться как тип переменных или как аргументы шаблона. Ни одна из этих функций не нужна для вашей коллекции функций. Поэтому предпочтительнее использовать инструмент, который не обладает этими функциями, чтобы случайно не использовать класс.
Из этого следует, что использование пространства имен сразу же дает понять всем пользователям вашего кода, что это набор функций, а не план создания объектов.
источник
Полностью статический класс выполнит свою работу, но это все равно, что ехать на 53-футовом полу грузовике в продуктовый магазин за чипсами и сальсой, когда подойдет четырехдверный седан (то есть, это излишне). Классы идут с небольшим количеством дополнительных накладных расходов, и их существование может создать у кого-то впечатление, что создание экземпляра может быть хорошей идеей. Бесплатные функции, предлагаемые C ++ (и C, где все функции свободны), этого не делают; они просто функции и ничего больше.
На самом деле, нет. Первоначальная цель
static
в C (и позже C ++) состояла в том, чтобы предложить постоянное хранилище, которое можно использовать на любом уровне области:Вы можете вывести область действия на уровень файла, что делает его видимым для всех более узких областей, но не за пределами файла:
Закрытый статический член класса в C ++ служит той же цели, но ограничен областью действия класса. Техника, использованная в
counter()
приведенном выше примере, также работает внутри методов C ++, и я бы порекомендовал ее использовать, если переменная не должна быть видимой для всего класса.источник
Если функция не поддерживает состояние и реентерабельна, кажется, что нет смысла помещать ее в класс (если это не предписано языком). Если функция поддерживает какое-то состояние (например, она может быть поточно-ориентированной только с помощью статического мьютекса), тогда статические методы класса кажутся подходящими.
источник
Большая часть дискуссии по теме здесь имеет смысл, хотя есть что - то очень фундаментальное о C ++ , что делает
namespaces
иclass
эс /struct
S очень разные.Статические классы (классы, в которых все члены являются статическими, а класс никогда не будет создан) сами являются объектами. Они не просто
namespace
содержат функции.Шаблонное метапрограммирование позволяет нам использовать статический класс в качестве объекта времени компиляции.
Учти это:
Чтобы использовать его, нам нужны функции, содержащиеся внутри класса. Пространство имен не будет работать здесь. Рассмотреть возможность:
Теперь, чтобы использовать это:
Пока новый распределитель предоставляет функцию
allocate
and,release
которая совместима, переключение на новый распределитель легко.Этого нельзя достичь с помощью пространств имен.
Вам всегда нужны функции, чтобы быть частью класса? Нет.
Является ли использование статического класса антишаблоном? Это зависит от контекста.
В этом случае то, что вы пытаетесь достичь, вероятно, лучше всего будет достигнуто с помощью объектно-ориентированного программирования.
источник
Как сказал Джон Кармак:
«Иногда элегантная реализация - это просто функция. Не метод. Не класс. Не фреймворк. Просто функция».
Я думаю, что это в значительной степени подводит итог. Зачем вам делать это принудительно классом, если это явно не класс? C ++ обладает такой роскошью, что вы можете использовать функции; в Java все является методом. Тогда вам нужны вспомогательные классы, и их много.
источник