Пространства имен с внешней связью

c++ namespaces

13662 просмотра

3 ответа

У меня проблема в основном та же, что упоминается в «greentype» на http://www.cplusplus.com/forum/beginner/12458/

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

Рассмотрим следующий пример, где я хочу передать переменную 'i', определенную в основном коде, в функцию a ():


* nn.h: *

#ifndef _NN_H_
#define _NN_H_

namespace nn {
int i;
}
#endif

* main.cpp *

#include <iostream>
#include "nn.h"
using namespace std;
using namespace nn;

void a();

int main()
{
i=5;
a();
}

void a()
{
using namespace std;
using namespace nn;

i++;
cout << "i = " << i << endl;
}

Но теперь, если я положу определение () в отдельный файл ...


* a.cpp *

#include <iostream>
#include "nn.h"

void a()
{
using namespace std;
using namespace nn;

i++;
cout << "i = " << i << endl;
}

... тогда я получаю ошибку 'множественное определение' при компоновке (g ++ main.cpp a.cpp -o main). Если я сделаю объявление 'i' в заголовочном файле 'extern' (как это предлагается на других форумах), я получу ошибку 'undefined reference'. Я могу скомпилировать, когда 'i' объявлен как const в заголовке, но это не то, что я хочу.

Любые предложения с благодарностью.

Источник Размещён: 12.11.2019 09:05

Ответы (3)


13 плюса

Любой глобальный объект, например i, должен иметь ровно одно определение где-то в программе, но он может быть объявлен несколько раз.

Использование externбез инициализатора делает объявление просто декларацией. Это подходит для вашего заголовочного файла, но вы все равно должны его iгде-то определить . Помимо создания объявления заголовка, externвам также необходимо добавить определение (то есть копию объявления без extern) в один и только один из ваших исходных файлов.

Редактировать: Читая ваш вопрос, вы говорите, что хотите передать переменную в функцию. С точки зрения стиля и структуры кода это обычно не является хорошей причиной для использования общей (глобальной) переменной. При отсутствии каких-либо основополагающих причин вы обычно должны определить функцию, которая принимает параметр и передает значение (возможно, из локальной переменной) с вызывающего сайта в эту функцию через ее параметр.

Автор: CB Bailey Размещён: 02.10.2009 07:05

10 плюса

Заголовочный файл должен сказать:

namespace nn {
    extern int i;
}

Это «декларация», а не «определение». Затем вам нужно определение в одном и только одном файле:

namespace nn {
    int i = 1;
}

Конечно, гораздо лучший подход - просто не иметь глобалов.

Автор: janm Размещён: 02.10.2009 07:06

2 плюса

На самом деле это не имеет ничего общего с пространствами имен, и все это связано со связью, внешней или иной символикой iв ваших различных примерах. По умолчанию глобальные переменные имеют externсвязь, а глобальные constсимволы имеют staticсвязь - это объясняет, почему это работает, когда вы делаете iconst. Чтобы решить вашу проблему, один из способов - объявить i с внешней связью в заголовочном файле, а затем определить его только в одном из файлов реализации, как показано ниже:

заголовок:

extern int i;

переменный ток:

int i:

main.c:

int main()
{
  i = 1; // or whatever
}

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

Автор: 1800 INFORMATION Размещён: 02.10.2009 07:09
Вопросы из категории :
32x32