extern 与 namespace 的用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了extern 与 namespace 的用法相关的知识,希望对你有一定的参考价值。

下面的程序编译通过,连接出错:
无法解析的外部符号 "int data::x" (?x@data@@3HA)
谁能解其中的原因?谢谢!
//文件 main.cpp
#include<iostream>
#include"data.h"
using std::cout;
using std::endl;
int main()

cout<<data::x<<endl;
return 0;


//文件 data.cpp

int x =1;

//文件 data.h
namespace data

extern int x;

我就是想用namespace,把数据封装在里面。我只是想知道如何处理如cin,cout在std里, 为什么不会出现这种情况。
下面是头文件<iostream>
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1

#pragma GCC system_header

#include <bits/c++config.h>
#include <ostream>
#include <istream>

namespace std

extern istream cin; ///< Linked to standard input
extern ostream cout; ///< Linked to standard output
extern ostream cerr; ///< Linked to standard error (unbuffered)
extern ostream clog; ///< Linked to standard error (buffered)

#ifdef _GLIBCXX_USE_WCHAR_T
extern wistream wcin; ///< Linked to standard input
extern wostream wcout; ///< Linked to standard output
extern wostream wcerr; ///< Linked to standard error (unbuffered)
extern wostream wclog; ///< Linked to standard error (buffered)
#endif
static ios_base::Init __ioinit;

#endif

/*extern在C和C++中是为了使用全局变量的。
说明变量具有外部链接属性!
在C和C++语言中,使用全局变量有两种方法。
其一:你在一个.cpp文件中定义了一个全局变量,如果你在
别的地方需要使用这个变量你可以用extern 声明
一下,告诉编译器这个变量是在别的.cpp文件定义过的
全局变量。
其二:也是建议用的,就是把在程序中要使用的全局变量放在
头文件中,你只需要在使用的地方用#include把头文件包含进
就可以了。
namespace命名空间是一个逻辑块,可以避免命名冲突。

具体到你这个地方,其实你在namespace data这个命名空间中,
你并没有声明一个变量,你只是用extern int x;告诉编译器
这个int 型的变量x是在别的.cpp文件中定义过的。你给的
那个补充说明也是这么一个意思。
就是在data.cpp
中你定义的int x =1;。这时候你在namespace data 命名空间中操作的
x是在data.cpp中定义的x。这个变量x并不是命名空间data中的,所以就会产生你那个链接错误,找不到符号。这时
你不妨在namespace data 中写一个函数,改写x的值,试试。

你要是想要在namespace data定义x,就得把前面的extern去掉。

在你这个程序中,只需要在main()函数中加上一句extern int x;
程序就可以正常运行,这说明你在main()函数中使用的是在data.cpp文件
中定义的全局变量。
#include<iostream>
#include"data.h"
using std::cout;
using std::endl;
int main()

extern int x;
cout<<x<<endl;
return 0;


也可以这样修改,
这时候使用的是在namespace data命名空间中定义的
x变量了。
//文件 data.h
namespace data

int x=100;


主函数文件:
#include<iostream>
#include"data.h"
using std::cout;
using std::endl;
using data::x;
int main()

cout<<x<<endl;
return 0;


*/
参考技术A 1、在C中,给全局变量,函数,加上 static,表示当前函数和变量的linkage 为 internal,这样,就可以在不同的unit 中定义同名的函数和变量了。
但是,加了static 的函数和变量就不用作为模板费类型参数了。(模板的非类型参数,必须是编译期确定的,exterl 性质的,整形常量或者指针常量)
2、在C++中,同样解决这种在不同的编译unit中定义同名的函数和变量的,这样就有了匿名的namespace, C++会为每个匿名的namespace生成一个唯一的 名字: __UNITQUE_NAMESPACE_NAME,并会再定义时后,加上 using namespace __UNITQUE_NAMESPACE_NAME,这样也就就解决了变量和函数名字冲突问题。
这里解决冲突的同时,并不会给函数和变量限定为 internal linkage。
参考技术B 之所以出现连接错误是因为:
在namespace data 中只是对 x 进行了声明,而非定义.即就是说,namespace data 中的int x不是namespace data 中的东西.这里只不过只是对x的一个声明而已,为的是在data中可以引用全局变量x
extern 表明int x只是一个声明,而非定义(告诉编译器这里的x在别的地方)
因为组合较多,下面是一种改法:
//main.cpp
#include<iostream>
#include"data.h"
using std::cout;
using std::endl;
int main()

cout<<x<<endl;
return 0;


//data.cpp
int x =1;

//data.h
extern int x;

至于namespace 在这里是用不到的:
这是由于如果x是namespace data中的,那么用extern岂不是多此一举(extern int data::x)而且还是错误的用法!
希望能解决你的问题! extern的详细用法见
http://zhidao.baidu.com/question/96882132.html
参考技术C 修改data.cpp文件:
//文件 data.cpp
namespace data

int x =1;

其余的都不变就可以了。这样x就是namespace data中的数据了,而不是一个所谓的无法解析的外部符号。而且不会因为data.h被包含在了其他的.cpp文件中而发重定义。因为data.h中只是申明x而矣。本回答被提问者和网友采纳

以上是关于extern 与 namespace 的用法的主要内容,如果未能解决你的问题,请参考以下文章

extern 用法,全局变量与头文件(重复定义)

C# 关键字extern用法

extern的用法

namespace基础介绍

vbs中namespace的用法

命名空间 extern的用法 static全局变量