extern 与 namespace 的用法

来源:百度知道 编辑:UC知道 时间:2024/06/18 04:54:53
下面的程序编译通过,连接出错:
无法解析的外部符号 "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)

1、在C中,给全局变量,函数,加上 static,表示当前函数和变量的linkage 为 internal,这样,就可以在不同的unit 中定义同名的函数和变量了。
但是,加了static 的函数和变量就不用作为模板费类型参数了。(模板的非类型参数,必须是编译期确定的,exterl 性质的,整形常量或者指针常量)
2、在C++中,同样解决这种在不同的编译unit中定义同名的函数和变量的,这样就有了匿名的namespace, C++会为每个匿名的namespace生成一个唯一的 名字: __UNITQUE_NAMESPACE_NAME,并会再定义时后,加上 using namespace __UNITQUE_NAMESPACE_NAME,这样也就就解决了变量和函数名字冲突问题。
这里解决冲突的同时,并不会给函数和变量限定为 internal linkage。

修改data.cpp文件:
//文件 data.cpp
namespace data
{
int x =1;
}
其余的都不变就可以了。这样x就是namespace data中的数据了,而不是一个所谓的无法解析的外部符号。而且不会因为data.h被包含在了其他的.cpp文件中而发重定义。因为data.h中只是申明x而矣。

之所以出现连接错误是因为:
在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;