Класс против пространства имен или класс и пространство имен? [закрытый]

как класс, так и пространство имен?

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

Я полагаю, что вопрос верхнего уровня: это хорошая идея? Наличие класса и пространства имен для связанных концепций?

вопрос нижнего уровня:

каков наилучший способ сделать это?

класс, вложенный в пространство имен?:

namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

или отдельный, одноранговый, класс и пространство имен?:

class Foo_Class {
    ...
};
namespace Foo_Namespace {
   // non-class free functions, etc.
}

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

следующее слишком долго, что приводит к действительно уродливые имена Foo_Namespace:: Foo_Class

namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

нет необходимости использовать какие-либо суффиксы или индикаторы в названии:

namespace Foo {
   class Foo {
       ...
   };
}

но тогда я оказываюсь неуверенным, когда смотрю на Foo ::bar(), если это свободная панель функций в пространстве имен ::Foo, то есть::Foo ::bar(), или функция-член в классе Foo в пространстве имен::Foo::Foo:: bar().

и такие имена, как ::Foo::Foo::bar все еще не, мм, приятно.

в настоящее время я делаю

не надо используйте любые суффиксы или индикаторы в названии:

namespace Foo_ns {
   class Foo {
       ...
   };
}

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

интересно, должен ли я возродить соглашение об именах, которое я не использовал годами: _c для класса, _ns для пространств имен:

namespace Foo_ns {
   class Foo_c {
       ...
   };
}

детали:

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

самая практическая причина, которую я знаю, чтобы использовать пространство имен в дополнение к классу-это то, что вам разрешено делать прямые объявления свободных функций в пространстве имен, но вам не разрешено делать прямые объявления некоторых методов класса. Т. е. с классом вы должны объявить все или ничего. В то время как со свободными функциями в целом и свободными функциями в пространствах имен в частности, вы можете объявить его по частям. Детали могут быть объявлены в разных файлах заголовков. Вместо#, включая массивную только заголовочную библиотеку для массивной class, вы можете использовать прямые объявления только для одной или двух функций. Так далее.

(см., например, http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Forward_Declarations, хотя Google netly опускается против прямых объявлений, а не включает заголовок.)

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

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

Я предпочитаю иметь класс, вложенных в пространства имен, Foo_ns/Foo_ns::Foo_c, а не иметь их как сверстников Foo_ns/Foo_c, потому что в классе порой нужны вспомогательные классы, например, Foo_ns/Foo_ns::Foo_c/Foo_ns::Foo_Helper_c. Если класс и пространство имен являются равноправными, кажется странным, чтобы Foo_ns/Foo_c но Foo_ns::Foo_Helper_c.

мне нравится пространств имен, потому что я согласен с Андреем Alexandresciu: http://laser.inf.ethz.ch/2012/slides/Alexandrescu/1-C++%20course%20parts%201%20and%202.pdf

 Class methods vs. free functions

 • Conventional wisdom: methods are cool, free functions are so 1960s
 • Yet:
   ◦ Free functions improve encapsulation over methods
   ◦ Free functions may be more general
   ◦ Free functions decouple better
   ◦ Free functions support conversions on their left-hand argument

  Surprising fact #2

    Making a function a method should be
    your last, not first, choice

  (c) 2012– Andrei Alexandrescu. 32 / 59

лучше создавать свободные функции, чем методы в классах.

но иногда классы просто должны использоваться, например, для шаблонов.

именование конвенции мудрым

я использовал Foo_ns / Foo_ns::Foo_c в прошлом

я использую Foo_ns / Foo_ns::Foo сейчас

(кстати, я склонен использовать Class_Names_With_Underscores_and_initial_caps, а не CamelCase.)

если это имеет смысл, я мог бы выделить суффикс _ns в пространстве имен-например, где пространство имен и класс(ы) не должны иметь одно и то же имя.

мне не нравится делать их с одинаковым именем. Рассмотрим конструктор для класса Foo внутри пространства имен foo:

::Foo::Foo:: Foo() против :: Foo_ns::Foo:: Foo()

последний не намного лучше, но немного меньше запутанным.

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

вывод

мой текущий BKM-Foo_ns / Foo_ns::Foo, т. е.

namespace Foo_ns {
   class Foo { 
   ...
   };
}

Я бы признателен за любые предложения, любые улучшения.

или я просто сломлен за это?

3 ответов


Я рекомендую иметь свой класс в пространстве имен с соответствующими функциями. Большая причина для этого


отдельные Foo_Class и Foo_Namespace определенно неправильно, это помешает вам использовать поиск, зависящий от аргумента, для поиска функций в пространстве имен, которые предназначены для использования с классом.

таким образом, класс должен быть вложен в пространство имен, если в пространстве имен будут функции, принимающие аргументы типа класса.

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

также необычно называть пространство имен начальной прописной буквой. Если ваши имена классов начинаются с заглавной буквы, вы можете перейти к namespace foo класс Foo, предоставив foo::Foo.

пространство имен не будет содержать более одного класса? Это звучит необычно для меня. Я бы назвал пространство имен после все его содержимое, только не один тип. Если это socket класс, я бы поставил его в networking пространство имен, для пример.

я думаю _c суффиксы на классах совершенно нелепы. Мне не нравится _ns суффикс на пространствах имен либо, его единственным спасением будет то, что Foo_ns::Foo лучше, чем Foo::Foo но я все равно сделаю это .

(остальная часть вашего вопроса просто кажется "почему пространства имен хороши", которые не должны действительно нуждаться в объяснении, они были добавлены к языку по какой-то причине, и хороший совет использовать нечлены для частей интерфейса которые не должны быть членами. Google прав, в общем, используйте заголовки, а не прямые объявления, что не меняет того факта, что вы можете повторно открыть пространства имен в отдельных заголовках, чтобы добавить новые имена в пространство имен, что является преимуществом, которое вы описываете.)


мне не нравятся "фрактальные" имена, повторяющие вещи, и я стараюсь избегать этого. Для вашего случая я бы попробовал что-то вроде пространства имен "Foo" и вложенного класса "Type". Возможно, какое-то другое имя было бы более подходящим, но это зависит от вашего фактического использования. Вот пример использования, который я повторяю снова и снова:

namespace status {
    enum type {
        invalid,
        okay,
        on_fire
    };
    // debug output helper
    char const* to_string(type t);
}

тип перечисления называется status::type, который может принимать значения как status::okay. Довольно читаемый ИМХО.