具有外部链接的命名空间

时间:2009-10-02 07:00:25

标签: c++ namespaces

我遇到的问题与'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()的定义放到一个单独的文件中......


* 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)。如果我在头文件'extern'中做'i'声明(如 在其他论坛中提出),我得到'未定义引用'错误。当'i'在标题中被声明为const时,我可以编译,但这不是我想要的。

任何建议都非常感谢。

3 个答案:

答案 0 :(得分:13)

任何全局对象,如i,必须在程序中的某个地方只有一个定义,但它可以声明多次。

在没有初始化程序的情况下使用extern使声明只是一个声明。这适用于您的头文件,但您仍必须在某处定义i。除了制作标题声明extern之外,您还需要在一个且只有一个源文件中添加一个定义(即没有extern的声明的副本)。

编辑:阅读您的问题,您说要将变量传递给函数。从样式和代码结构的角度来看,这通常不是使用共享(全局)变量的好理由。在没有任何重要原因的情况下,您通常应该定义一个函数,该函数接受一个参数并通过其参数将一个值(可能来自局部变量)从调用站点传递给该函数。

答案 1 :(得分:10)

头文件应该说:

namespace nn {
    extern int i;
}

这是“声明”而不是“定义”。然后,您需要在一个且只有一个文件中定义:

namespace nn {
    int i = 1;
}

当然,一个更好的方法就是根本没有全局变量。

答案 2 :(得分:2)

这与命名空间没有任何关系,而是与各种示例中的符号i的外部或其他方式的链接有关。默认情况下,全局变量具有extern链接,而全局const符号具有static链接 - 这解释了为什么它在您i const时有效。要解决您的问题,一种方法是在头文件中使用extern链接声明 i,然后只在其中一个实现文件中 define ,如图所示下面:

头:

extern int i;

交流转换器:

int i:

main.c中:

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

请注意,为了清楚起见,我删除了命名空间 - 最终结果是相同的。