由预处理引发名字空间(namespace)几点讨论
===================================================================================
讨论一:#include<iostream.h>与#include"iostream.h"的区别
前者是从系统文件开始搜索头文件,后者是从当前文件夹开始搜索头文件。后者如果在当前文件夹中没有搜索到,然后会到系统文件夹去接着搜索。一般包含系统自带的头文件用尖括号,包含自己定义的头文件用双引号。
讨论二 :<iostream>和<iostream.h>的区别
<iostream>和<iostream.h>是不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。
iostream.h是C的头文件库,iostream是C++标准头文件库,C++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。(但是因为早期C++继承了C的特性,为了兼容以前的C++代码,故保留了iostream.h的这种写法。早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,)目前后缀为.h的头文件c++标准已经明确提出不支持了(VC++8之后版本)。
因此,当使用<iostream.h>时,相当于在C中调用库函数,使用的是全局命名空间,也就是早期的C++实现;当使用< iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout.或是逐个定义如std::cout
讨论三:namespace
所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
1、直接指定标识符。例如std::ostream而不是ostream.
完整语句如下:
std::cout << std::hex << 3.4 << std::endl;
2、使用using关键字。
using std::cout;
using std::endl;
以上程序可以写成
cout << std::hex << 3.4 << endl;
3、最方便的就是使用using namespace std;
例如:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写:
cout << hex << 3.4 << endl;
因为标准库非常的庞大,所程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准 库中的一切都被放在名字空间std中。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。
讨论四、使用using namespace std;的弊端:
C++ PRIMER, EFFECTIVE C++上推荐使用分别定义如下
using std::cin;
using std::cout;
举例(网上的例子):
用了VISUAL C++写一个小程序如下:
#include <iostream>
using namespace std;//全局使用std
template <typename T>
T max (T a,T b)
{
return ((a>b)?a:b);
}
void main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}
在VC++9.0中(visual studio2008)编译不通过出现一个错误:
错误 1 error C2668: “max”: 对重载函数的调用不明确
但是将这段代码放到VC++ 6.0下编译正常,原因在std命名空间下也有一个MAX函数。利用转到定义功能可以看到微软是怎么写MAX函数的。程序开始使用了std标准库,但是又自己定义了max(x,y),所以编译器不知道你要用哪个,因为你没有明确指出重载。
改写代码如下:
#include <iostream>
using std::cin;
using std::cout;
using std::endl;//仅所列函数使用std,故max明确调用自己的定义的
template <typename T>
T max (T a,T b)
{
return ((a>b)?a:b);
}
int main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}
讨论五、为什么引入namespace?
在全局名字空间域(简称 全局域)引入的全局实体必须有唯一的名字,即函数和对象不能有相同的名字,无论它们是否在同一程序文本中被声明。但是实际情况,我们很难做到自己命名的函数和对象不与标准库std或者程序员的库相同,这样就很容易造成全局域污染问题。引入namespace可以在全局域下划分出自己的名字空间域,进而避免污染问题。
举例:
#include <iostream>
using namespace std;
void print()
{
int score = 87;
string name = "Li Hua";
cout<<"name:"<< name.c_str()<<endl;
cout<<"score:"<<score<<endl;
}
namespace myspace{
void print()
{
int score = 97;
string name = "Han meimei";
cout<<"name:"<< name.c_str()<<endl;
cout<<"score:"<<score<<endl;
}
}
void main()
{
print();
myspace::print();
}
输出结果:
name:Li hua
score:87
name: Han meimei
score: 97
==========================再次重申异同=========================
#include <iostream>
using namespace std; //必须放在include之后
void main()
{
cout << "hello!" << endl;
}
如果不用using namespace std;
那么
#include <iostream>
void main()
{
std::cout << "hello!" << endl;
}
必须写成 std::cout << "hello!" <<std::endl;
===============================================================