Подтвердить что ты не робот

Использование пространства имен вместо статического класса в С++?

Хорошо или хорошо использовать пространство имен как статический класс? Например:

namespace MyStaticFunctions {
    void doSomething();
}

Versus:

class MyStaticFunctions {
    static void doSomething();
}
4b9b3361

Ответ 1

В С++ нет такой вещи, как "статический класс", поэтому с точки зрения С++ вы не используете ее как "статический класс", вы используете ее "как пространство имен". Разумеется, практика использования пространств имен объединяла функции вместе.

Тем не менее, насколько вы хотите, чтобы группы были. Для библиотек С++ не так просто использовать единое пространство имен для всего публичного интерфейса. Это может стать неожиданностью для тех, кто привык (скажем) Java, где классы часто используются для группировки меньшего количества статических методов. Поскольку С++ был здесь первым, вы могли бы сказать, что Java использует классы как пространства имен.

Итак, в С++ вы не склонны видеть классы, похожие на java.util.Collections или java.lang.Math, заполненные статическими членами. Если вам нужны группы таких функций, как на С++, используйте пространства имен.

Исключение (не всегда ли существует специальный случай в С++?) - это такие типы признаков, как std::numeric_limits<T>, где параметр шаблона делает класс тем, что пространство имен не может сделать. Вы можете определить пространство имен numeric_limits, содержащее шаблоны функций max<T>(), min<T>() и т.д., Но это не так хорошо. Во-первых, он группирует вещи несколько иначе, тип T появляется "ниже иерархии". Во-вторых, это не делает все, что делает тип признаков, потому что нет такой вещи, как "шаблон объекта", который позволит вам определить значение numeric_limits::digits<T>.

Я не знаю, С# достаточно, чтобы прокомментировать практическое использование статических классов там, но AFAIK это просто класс, ограниченный отсутствием нестатических членов, поэтому он аналогичен тем Java-классам.

Ответ 2

В С++ вы на самом деле поощряетесь на уровне языка использовать namespace, а не class, содержащий только static методы из-за поиска Koenig (также известный как поиск аргумента).

Пример:

namespace geometry {
    struct Point { int x, y; };

    double distance_from_center(Point const& p) {
        return sqrt(p.x * p.x + p.y + p.y);
    }
} // namespace geometry

int main() {
    geometry::Point const p{3, 4}; // must qualify

    std::cout << distance_from_center(p) << "\n"; // not qualified
}

Если distance_from_center записывается как метод static в class, тогда вам нужно явно указывать его каждый раз.

Ответ 3

Это сложный и интересный вопрос для меня лично, поэтому решил поделиться своим скромным мнением

Учитывая разницу между "статическим" классом (только статическими членами) и пространством имен:

  • пространство имен может быть разбросано по нескольким файлам: дополнительная гибкость, но их следует использовать осторожно.
  • пространство имен предоставляет зависимый от аргументов поиск (см. Маттиу М. ответ): полезно в конкретных ситуациях
  • "статический" класс может иметь модификаторы доступа и может формировать иерархию: я думаю, что частные члены, объявленные в интерфейсе класса и видимые для своих клиентов, являются функциями С++, которые были продиктованы более техническими, а не логическими причинами. Я не вижу преимуществ частных статических членов. Защищенные члены для "статической" иерархии? Никогда не видел.
  • "статический" класс может быть "шаблоном", помимо членов шаблона: см. ответ Стив Джессопа для отличного примера из STL

С точки зрения обслуживания иногда вы выбираете класс "статический" (например, singleton), но тогда требование изменилось, и вам нужно несколько экземпляров. "Статический" класс легче преобразовать, чем пространство имен.

И, наконец, чтобы ответить на ваш вопрос:

если вам не нужны специальные функции "статического" класса или пространства имен, используйте то, что вам больше нравится:)

Ответ 4

Это зависит.

Является ли метод логически связан с классом? Если это так, сделайте его членом, иначе поместите его в пространство имен.

Функционально, они одинаковы, но есть больше кода, чем функция, не так ли? Например, рассмотрим метод, который возвращает имя класса:

struct MyClass
{
    static std::string getName() { return "MyClass"; }
}

Вы могли бы поместить метод снаружи в namespace и получить тот же результат, но он логически принадлежит классу.