Различия между абстрактным классом со статическими функциями и регулярными функциями в пространстве имен? [Дубликат]

бит 2mantissa + 1 + 1

+1 в экспоненте (бит мантиссы + 1) состоит в том, что если мантисса содержит abcdef..., то число, которое оно представляет, фактически 1.abcdef... × 2^e, обеспечивая дополнительный неявный бит точности.

Для float это 16 777 217 (224 + 1). Для double это 9 007 199 254 740 993 (253 + 1).

>>> 9007199254740993.0
9007199254740992
232
задан Stephen Canon 16 September 2009 в 21:00
поделиться

7 ответов

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

  • Вам не нужно определять все в одном заголовке
  • You не нужно раскрывать всю свою реализацию в заголовке
  • Вы не можете using члена класса; вы можете using член пространства имен
  • Вы не можете using class, хотя using namespace не так часто бывает хорошей идеей
  • Использование класса подразумевает, что есть некоторые объект, который будет создан, когда его действительно нет

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

10
ответ дан coppro 22 August 2018 в 00:12
поделиться
  • 1
    «Вам не нужно раскрывать всю свою реализацию в заголовке». вы не делаете, когда используете класс. – Vanuan 22 June 2011 в 08:59
  • 2
    Более того: если вы используете пространства имен, вы не можете выставить всю свою реализацию в заголовке (в итоге вы получите несколько определений символов). Встроенные функции класса-члена позволяют это сделать. – Vanuan 22 June 2011 в 09:38
  • 3
    @Vanuan: Вы можете открыть реализации пространства имен в заголовке. Просто используйте ключевое слово inline для удовлетворения ODR. – Thomas Eding 6 December 2012 в 01:24
  • 4
    @ThomasEding не нужно! = Can – Vanuan 6 December 2012 в 04:34
  • 5
    @Vanuan: только одна вещь гарантируется компилятором при использовании inline, и это НЕ "встраивание" тело функции. реальная (и гарантированная стандартной) целью inline заключается в предотвращении множества определений. Читайте о «Правиле с одним определением». для C ++. Кроме того, связанный вопрос SO не собирался из-за предварительно скомпилированных проблем заголовков, а не проблем с ODR. – Thomas Eding 6 December 2012 в 20:33

Есть много людей, которые не согласились бы со мной, но это то, как я это вижу:

Класс по существу является определением определенного типа объекта. Статические методы должны определять операции, которые тесно связаны с этим определением объекта.

Если вы просто собираетесь иметь группу связанных функций, не связанных с базовым объектом или определением типа объекта , то я бы сказал, что вы идете только с пространством имен. Для меня, концептуально, это гораздо более разумно.

Например, в вашем случае спросите себя: «Что такое MyMath?» Если MyMath не определяет какой-либо объект, тогда I скажет: не делайте его классом.

Но, как я уже сказал, я знаю, что есть много люди, которые (даже яростно) не согласятся со мной на этом (в частности, разработчики Java и C #).

47
ответ дан Dan Tao 22 August 2018 в 00:12
поделиться
  • 1
    У вас есть очень чистая перспектива. Но практически говоря, класс со статическими методами может пригодиться: вы можете typedef их использовать в качестве параметров шаблона и т. Д. – Shog9♦ 16 September 2009 в 20:27
  • 2
    Это потому, что у людей и C # нет выбора. – Martin York 16 September 2009 в 20:27
  • 3
    – Martin York 16 September 2009 в 20:28
  • 4
    @Dan: предположительно, тот, который нуждался в математических подпрограммах и хотел поддержать «включение», различные реализации. – Shog9♦ 16 September 2009 в 20:37
  • 5
    @Dan: «Я думаю, что если кто-то заинтересован в использовании класса в качестве параметра шаблона, этот класс почти наверняка определяет некоторый базовый объект. & Quot; Нет, совсем нет. Подумайте о чертах. (Тем не менее, я полностью согласен с вашим ответом.) – sbi 16 September 2009 в 21:17

Еще одна причина использования класса - вариант использования спецификаторов доступа. Затем вы можете разбить свой публичный статический метод на более мелкие частные методы. Открытый метод может вызывать несколько частных методов.

0
ответ дан Milind T 22 August 2018 в 00:12
поделиться
  • 1
    Модификаторы доступа классны, но даже самый private метод более доступен, чем метод, прототип которого вообще не публикуется в заголовке (и, таким образом, остается невидимым). Я даже не упоминаю о лучшей инкапсуляции, предлагаемой анонимными функциями с именами. – paercebal 17 February 2012 в 20:00
  • 2
    Частные методы - это ИМО, уступающие скрытию самой функции в реализации (файл cpp) и никогда не подвергая ее воздействию в файле заголовка. Расскажите об этом в своем ответе и о том, почему вы предпочитаете использовать private участников. До тех пор -1. – nonsensickle 31 March 2014 в 00:19
  • 3
    @nonsensickle Возможно, он имеет в виду, что мамонтовая функция с множеством повторяющихся разделов может быть разбита безопасно, скрывая оскорбительные подразделы за частным, останавливая других от попадания на них, если они опасны / требуют очень осторожного использования. – Troyseph 13 November 2015 в 14:09
  • 4
    @Troyseph даже в этом случае вы можете скрыть эту информацию внутри неназванного пространства имен в файле .cpp, который сделает его закрытым для этой единицы перевода, не передавая лишней информации никому, кто читает файл заголовка. Фактически, я пытаюсь отстаивать идиому PIMPL. – nonsensickle 15 November 2015 в 05:09
  • 5
    Вы не можете поместить его в файл .cpp, если хотите использовать шаблоны. – Yay295 16 July 2018 в 22:16

Я бы предпочел пространства имен, таким образом, вы можете иметь личные данные в анонимном пространстве имен в файле реализации (поэтому он не должен отображаться в заголовке вообще, а не private). Другим преимуществом является то, что через using ваше пространство имен клиенты методов могут отказаться от указания MyMath::

3
ответ дан Motti 22 August 2018 в 00:12
поделиться
  • 1
    Вы также можете иметь личные данные в анонимном пространстве имен в файле реализации с классами. Не уверен, что я следую вашей логике. – Patrick Johnmeyer 17 September 2009 в 01:58

По умолчанию использовать функции с именами.

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

В объектно-ориентированном коде

Скотт Мейерс написал целый предмет для своей эффективной книги на C ++ по этой теме: «Предпочитайте функции, не являющиеся членами-членами, для функций-членов». Я нашел онлайн-ссылку на этот принцип в статье из Herb Sutter: http://www.gotw.ca/gotw/084.htm

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

Функции имен, если только объявленный «друг» не имеет доступа к внутренним классам, тогда как статические методы имеют.

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

Расширение I

Добавление кода в класс '.

В C # вы можете добавлять методы в класс, даже если у вас нет доступа к нему. Но в C ++ это невозможно.

Но, все еще на C ++, вы все равно можете добавить функцию с именами, даже в класс, который кто-то написал для вас.

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

Расширение II

Сторона -эффект предыдущей точки, невозможно объявить статические методы в нескольких заголовках. Каждый метод должен быть объявлен в одном классе.

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

Extension III

Основная прохлада пространства имен заключается в том, что в некотором коде вы можете не упоминать об этом, если используете ключевое слово «using»:

#include <string>
#include <vector>

// Etc.
{
   using namespace std ;
   // Now, everything from std is accessible without qualification
   string s ; // Ok
   vector v ; // Ok
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

И вы можете даже ограничить «загрязнение» одним классом:

#include <string>
#include <vector>

{
   using std::string ;
   string s ; // Ok
   vector v ; // COMPILATION ERROR
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

Этот «шаблон» является обязательным для правильного использования почти стандартного икота свопа.

И это невозможно делать со статическими методами в классах.

Итак, пространства имен C ++ имеют свою собственную семантику.

Но она идет дальше, поскольку вы можете комбинировать пространства имен способом, подобным наследованию.

Например, если у вас есть пространство имен A с функцией AAA, пространство имен B с функцией BBB, вы можете объявить пространство имен C и привести AAA и BBB в это пространство имен с использованием ключевого слова.

Заключение

Пространства имен для n amespaces. Классы предназначены для классов.

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

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

И в вашем случае вам нужны пространства имен.

205
ответ дан pmdj 22 August 2018 в 00:12
поделиться
  • 1
  • 2
    @dashesy: ​​ пространства имен и статические методы не имеют ничего общего с потоками, поэтому да, пространства имен лучше, потому что пространства имен почти всегда лучше статических методов. Если одно, то статические методы имеют доступ к переменным-членам класса, поэтому они имеют меньшее значение инкапсуляции, чем пространства имен. И выделение данных еще более важно в поточном исполнении. – paercebal 17 February 2012 в 19:41
  • 3
    @ paercebal- спасибо, я использовал статические методы класса для функций потоков. Теперь я понимаю, что я злоупотреблял классом как пространство имен, так что, по-вашему, лучший способ иметь несколько потоков в одном объекте? Я тоже задал этот вопрос на SO, я ценю, если вы можете пролить некоторый свет (здесь или в самом вопросе) – dashesy 17 February 2012 в 19:56
  • 4
    @dashy: Вы просите о неприятностях. То, что вы хотите с разными потоками, - это изолировать данные, которые не должны использоваться совместно, поэтому наличие нескольких потоков, имеющих привилегированный доступ к личным данным класса, является плохой идеей. Я бы спрятал один поток внутри класса и обязательно выделил данные для этого потока из данных для основного потока. Конечно, данные, которые должны быть разделены, могут быть членами этого класса, но они все равно должны быть синхронизированы (блокировки, атомы и т. Д.). Я не уверен, сколько у вас libs, но использование задач / async еще лучше. – paercebal 17 February 2012 в 21:40
  • 5
    Ответ paercebal должен быть принят! Еще одна ссылка для почти стандартного swap () через пространство имен + ADL - & gt; [Д0] stackoverflow.com/questions/6380862/… – Gob00st 4 October 2012 в 18:13

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

0
ответ дан rocd 22 August 2018 в 00:12
поделиться
  • 1
    & quot; [сохранение вещей] в анонимном пространстве имен файла реализации [имеет] больший объем, чем их внутри класса & quot; - нет. в случаях, когда привилегированный доступ к членам не требуется, анонимный материал с именами более частный , чем private:. и во многих случаях, когда требуется привилегированный доступ , , который может быть учтен. самая «частная» функция - та, которая не появляется в заголовке. private: методы никогда не смогут пользоваться этим преимуществом. – underscore_d 8 April 2016 в 13:45
  • Если вам нужны статические данные, используйте статические методы.
  • Если они являются функциями шаблона, и вы хотите, чтобы у вас есть возможность указать набор параметров шаблона для всех функций вместе, используйте статические методы в классе шаблона.

В противном случае используйте функции с именами.


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

template<typename T, int decimalPlaces>
class MyMath
{
   // routines operate on datatype T, preserving at least decimalPlaces precision
};

// math routines for manufacturing calculations
typedef MyMath<double, 4> CAMMath;
// math routines for on-screen displays
typedef MyMath<float, 2> PreviewMath;

Если вам это не нужно, тогда всеми средствами использует пространство имен.

15
ответ дан Shog9 22 August 2018 в 00:12
поделиться
  • 1
    так называемые статические данные могут быть данными уровня пространства имен в файле реализации пространства имен, это уменьшает сцепление еще больше, поскольку оно не должно отображаться в заголовке. – Motti 16 September 2009 в 20:26
  • 2
    Статические данные не лучше, чем глобальные глобальные области пространства имен. – coppro 16 September 2009 в 20:27
  • 3
    @coppro. Это, по крайней мере, один шаг вверх по эволюционной цепочке от случайных глобалов, поскольку они могут быть сделаны частными (но в остальном согласны). – Martin York 16 September 2009 в 20:30
  • 4
    @Motti: OTOH, если вы хотите его в заголовке (встроенные / шаблонные функции), вы вернетесь к уродливому об этом. – Shog9♦ 16 September 2009 в 20:31
  • 5
    Интересный пример: использование класса в виде сокращения, чтобы избежать повторения аргументов template! – underscore_d 8 April 2016 в 13:40
Другие вопросы по тегам:

Похожие вопросы: