Создание пространства имен 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;
  }
} 

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

ссылки77
источник

Ответы:

37

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

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

впраджан
источник
55

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

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

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

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

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

Михаил Крелин - хакер
источник
Я бы не назвал это заблудшим, так как он соответствует закрытию }в самом конце. Однако я бы назвал эту пару скобок излишней;)
blubberdiblub
@blubberdiblub, вопрос отредактировали, если бы вы проверили оригинальную версию, вы бы назвали ее бредовой ;-)
Майкл Крелин - хакер
1

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

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

Holgac
источник
1
Я не думаю, что он компилируется, но не потому, что есть разница, а потому, что есть паразит {;-)
Майкл Крелин - хакер
Разница в том, что Foo :: TheFunc () объявлен в глобальном пространстве имен, тогда как он определен в пространстве имен X.
bert-jan
1

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

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

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

AlexTheo
источник
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;
}

источник