Создание пространства имен C ++ в заголовке и источнике (cpp)


88

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

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

Пример:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

Если нет разницы, какая форма предпочтительнее и почему?

Ответы:


37

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

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


55

Разница между «пространством имен X» и «использованием пространства имен X» заключается в том, что в первом случае любые новые объявления будут находиться под этим пространством имен, а во втором - нет.

В вашем примере нет нового объявления - поэтому нет разницы, следовательно, нет предпочтительного способа.


Это зависит от проекта и стиля. Часто для загрузки файлов в модуле существует одно основное пространство имен, и второй стиль имеет смысл.
Николас Уилсон

8

Нет никаких штрафов за производительность, так как результат может быть таким же, но размещение вашего Fooв пространстве имен неявно вводит двусмысленность, если у вас есть Foos в разных пространствах имен. Вы действительно можете получить свой код fubar. Я бы рекомендовал избегать использования usingдля этой цели.

А у вас заблудший {после using namespace;-)


Я бы не назвал это заблудшим, так как он соответствует закрытию }в самом конце. Однако я бы назвал эту пару скобок излишней;)
blubberdiblub

@blubberdiblub, вопрос отредактировали, если бы вы проверили оригинальную версию, вы бы назвали ее бредовой ;-)
Майкл Крелин - хакер

1

Если второй компилируется, отличий быть не должно. Пространства имен обрабатываются во время компиляции и не должны влиять на действия во время выполнения.

Но что касается дизайна, второй вариант ужасен. Даже если он компилируется (не уверен), в этом нет никакого смысла.


1
Я не думаю, что он компилируется, но не потому, что есть разница, а потому, что есть паразит {;-)
Майкл Крелин - хакер

Разница в том, что Foo :: TheFunc () объявлен в глобальном пространстве имен, тогда как он определен в пространстве имен X.
bert-jan

1

Foo :: TheFunc () не находится в правильном пространстве имен в случае VS. Используйте void X :: Foo :: TheFunc () {}, чтобы реализовать функцию в правильном пространстве имен (X).


Вопрос немного давний, но знаете ли вы, каковы последствия этого? т.е. столкнетесь ли вы с какими-либо проблемами, связанными с тем, как его VS case объявляет функции в пространстве имен, но определяет их вне его?
Адам Гудвин

1

В случае, если вы оберните только содержимое .h, которое вы должны написать, используя пространство имен ... в файле cpp, иначе вы каждый раз будете работать с допустимым пространством имен. Обычно вы оборачиваете файлы .cpp и .h, иначе вы рискуете использовать объекты из другого пространства имен, что может вызвать множество проблем.


0

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

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}

0

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

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.