Допустим, у меня есть или я собираюсь написать набор связанных функций. Допустим, они связаны с математикой. Организационно, я должен:
- Напишите эти функции и поместите их в мое
MyMath
пространство имен и обратитесь к ним черезMyMath::XYZ()
- Создайте класс с именем
MyMath
и сделайте эти методы статичными и обращайтесь к аналогичнымMyMath::XYZ()
Почему я выбрал одно из другого в качестве средства организации своего программного обеспечения?
c++
namespaces
static-methods
RobertL
источник
источник
Ответы:
По умолчанию используйте функции пространства имен.
Классы предназначены для создания объектов, а не для замены пространств имен.
В объектно-ориентированном коде
Скотт Мейерс написал целую статью для своей книги «Эффективное C ++» на эту тему: «Предпочитайте функции, не являющиеся членами, не являющимися друзьями, функциям-членам». Я нашел онлайн ссылку на этот принцип в статье Херба Саттера:http://www.gotw.ca/gotw/084.htm
Важно знать следующее: в C ++ функции в том же пространстве имен, что и класс, принадлежат интерфейсу этого класса (потому что ADL будет искать эти функции при разрешении вызовов функций).
Функции пространств имен, если они не объявлены «другом», не имеют доступа к внутренним объектам класса, в то время как статические методы имеют.
Это означает, например, что при ведении вашего класса, если вам нужно изменить внутренние компоненты вашего класса, вам нужно будет искать побочные эффекты во всех его методах, включая статические.
Расширение I
Добавление кода в интерфейс класса.
В C # вы можете добавлять методы в класс, даже если у вас нет к нему доступа. Но в C ++ это невозможно.
Но все же в C ++ вы все еще можете добавить функцию пространства имен даже в класс, который кто-то написал для вас.
С другой стороны, это важно при разработке вашего кода, потому что, помещая ваши функции в пространство имен, вы разрешаете своим пользователям расширять / дополнять интерфейс класса.
Расширение II
Побочным эффектом предыдущего пункта является невозможность объявления статических методов в нескольких заголовках. Каждый метод должен быть объявлен в одном классе.
Для пространств имен функции из одного и того же пространства имен могут быть объявлены в нескольких заголовках (лучшим примером является почти стандартная функция подкачки).
Расширение III
Основная крутость пространства имен заключается в том, что в некотором коде вы можете не упоминать его, если используете ключевое слово «using»:
И вы даже можете ограничить «загрязнение» одним классом:
Этот «шаблон» является обязательным для правильного использования почти стандартной идиомы подкачки.
И это невозможно сделать со статическими методами в классах.
Итак, пространства имен C ++ имеют свою семантику.
Но это идет дальше, так как вы можете комбинировать пространства имен способом, похожим на наследование.
Например, если у вас есть пространство имен A с функцией AAA, пространство имен B с функцией BBB, вы можете объявить пространство имен C и ввести AAA и BBB в это пространство имен с помощью ключевого слова, используя.
Вывод
Пространства имен предназначены для пространств имен. Занятия для занятий.
C ++ был спроектирован таким образом, чтобы каждая концепция была разной и в разных случаях использовалась по-разному как решение разных проблем.
Не используйте классы, когда вам нужны пространства имен.
И в вашем случае вам нужны пространства имен.
источник
Есть много людей, которые не согласятся со мной, но вот как я это вижу:
Класс - это, по сути, определение определенного вида объекта. Статические методы должны определять операции, которые тесно связаны с определением этого объекта.
Если вы просто хотите иметь группу связанных функций, не связанных с базовым объектом или определением типа объекта , то я бы сказал, что использовать только пространство имен. Просто для меня, концептуально, это намного разумнее.
Например, в вашем случае спросите себя: «Что такое MyMath?» Если
MyMath
не определить вид объекта, я бы сказал: не делайте его классом.Но, как я уже сказал, я знаю, что есть много людей, которые (даже яростно) не согласны со мной в этом (в частности, разработчики на Java и C #).
источник
typedef
их использовать, использовать их в качестве параметров шаблона и т. Д.В противном случае используйте функции пространства имен.
В ответ на комментарии: да, статические методы и статические данные имеют тенденцию к чрезмерному использованию. Вот почему я предложил только два взаимосвязанных сценария, где я думаю, что они могут быть полезны. В конкретном примере OP (набор математических подпрограмм), если он хочет иметь возможность задавать параметры - скажем, основной тип данных и точность вывода - которые будут применяться ко всем подпрограммам, он может сделать что-то вроде:
Если вам это не нужно, то все средства использовать пространство имен.
источник
template
аргументов!Вы должны использовать пространство имен, потому что пространство имен имеет много преимуществ перед классом:
using
ученик; Вы можетеusing
член пространства именusing class
, хотяusing namespace
не все так часто хорошая идеяСтатические члены, на мой взгляд, очень сильно перегружены. Они не являются реальной необходимостью в большинстве случаев. Функции статических членов, вероятно, лучше использовать в качестве функций области файла, а члены статических данных - это просто глобальные объекты с лучшей, незаслуженной репутацией.
источник
inline
ключевое слово, чтобы удовлетворить ODR.inline
, и она НЕ "встраивает" тело функции. Реальная (и гарантирован стандарт) цельinline
состоит в предотвращении нескольких определений. Читайте об «одном правиле определения» для C ++. Кроме того, связанный вопрос SO не компилировался из-за проблем с предварительно скомпилированными заголовками вместо проблем ODR.Я бы предпочел пространства имен, таким образом, вы можете хранить личные данные в анонимном пространстве имен в файле реализации (поэтому он не должен отображаться в заголовке вообще, в отличие от
private
членов). Другое преимущество заключается в том, чтоusing
вашими именами клиенты могут отказаться от указания методов.MyMath::
источник
Еще одна причина использовать класс - Возможность использовать спецификаторы доступа. Затем вы можете разбить ваш публичный статический метод на меньшие приватные методы. Открытый метод может вызывать несколько частных методов.
источник
private
метод является более доступным, чем метод, прототип которого вообще не публикуется в заголовке (и, следовательно, остается невидимым). Я даже не упоминаю о лучшей инкапсуляции, предлагаемой анонимно распределенными функциями..cpp
файле, что сделало бы его приватным для этого модуля перевода, не предоставляя никакой лишней информации любому, кто читает файл заголовка. По сути, я пытаюсь отстаивать идиому PIMPL..cpp
файл, если хотите использовать шаблоны.И пространство имен, и метод класса имеют свое применение. Пространство имен может быть распределено по файлам, однако это является недостатком, если вам нужно заставить весь связанный код помещаться в один файл. Как упомянуто выше, класс также позволяет вам создавать частные статические члены в классе. Вы можете иметь его в анонимном пространстве имен файла реализации, однако это все же больше, чем иметь их внутри класса.
источник
private:
те. и во многих случаях , когда привилегированный доступ , кажется , потребуется, что может быть вынесено. самая частная функция - это функция, которая не появляется в заголовке.private:
методы никогда не могут пользоваться этим преимуществом.