Класс против пространства имен или класс и пространство имен? [закрытый]
как класс, так и пространство имен?
этот вопрос касается шаблона, который я вижу, что использую все больше и больше: имея как класс, так и пространство имен для связанных концепций. Я думаю, что это мотивировано в основном артефактами языка 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
. Довольно читаемый ИМХО.