菜鸟笔记
提升您的技术认知

命名空间的使用与详解

关于命名空间的使用与详解

昨天晚上一同学给我讲了下命名空间namespace,讲完后,恩,我以为自己懂了。 今天借着在用heritrix在seekda.com上爬网站的时间,我想着自己老是说要用用C++的模板(template)来试着写东西的,但一直没搞。现在正好有时间可以来试验一下的,于是就试着写了两个实质一样的小程序。就是通过这两个小程序,引发了后面一系列的问题,同时也暴露出了我的不足。

       第一个程序是这样的:

#include <iostream>
template <class T> 
inline const T max(T a,T b)
{
       return a>b? a:b;
}
int main()
{
    std::cout<<max(1,2);
    while(1);
    return 0;
}

使用模板的好处是不言而喻的,从这个例子就可以看出。我们现在比较的是两个整形数1,2的大小,由于有了模板函数的存在,我们可以不用预先定义参数的类型,那么同时也可以进行浮点数之间的比较,甚至整形数和浮点数的比较。这样我们就不用像原来那样进行函数重载,针对一个特定参数类型,再写出一个功能相同,但是仅参数不同额函数来,大大减轻了负担。同时template并不是一次编译便生出所有参数类型的代码,而是针对某个被使用的类型来编译,因此在遇到一个模板函数时编译器才会对这个函数编译。

OK,关于模板的东西先说这些,接下来说说我今天遇到的问题,其实上面这个函数是最终调试好的程序,预先自己写的是这样的:

#include <iostream>
using namespace std;
template <class T>
inline const T max(T a,T b)
{
       return a>b? a:b;
}
int main()
{
    cout<<max(1,2);
    while(1);
    return 0;
}

编译后报错:C:\Documents and Settings\Administrator\桌面\tmp\stl.cpp call of overloaded `max(int, int)' is ambiguous意思就是说:在对max()时出现歧义。出现这种错误的原因就在于:我滥用了std的命名空间。

//

命名空间的出现是为了解决名字冲突问题的。因为C++得代码太多,很多人都为他写了库,那么难免就会出现命名冲突的问题,比如杨师兄举的例子:一个科学计算库里面可能有个函数叫times,表示倍乘运算,而在另一个网络通讯库里面也可能有一个函数叫times,表示获取当前时间。那么在你同时包含这两个库,同时用到times时,编译时就会出错。以前人们解决这个问题的方法是在函数前面加上前缀或后缀,让函数保证不同名,但是随着C++的壮大发展,光靠取不同的函数名,怎么能算是一种很好的解决冲突的方法呢,于是命名空间就诞生了。我们在写某个类库时给他定一个专有的空间名,那么在这空间内部的函数,他就是唯一的,即使外界有和他重名的,也无关。如果我们想在外部调用这个空间里的函数,只需通过域操作符就可以完成了。

比如:

namespace net                  namespace calculate

{                                    {

int times                            int times

          {                                       {

           ...                                      ...

          }                                        }

}                                     }

用的时候只需通过net::times()和calculate::times()就可以了。但是要注意的是,在我们的程序中用到这些库的时候,这些函数仍然是全局函数,只是他的名字所在的空间不是全局的了,也就是说他的名字不会对其他同名函数产生什么影响。

分割线包围的部分就是昨天晚上杨给我讲的关于命名空间的知识。那么现在再来看看,上面我写的那个报错的程序。现在就很明显可以看出,错误是由什么导致的了。我在程序开头不明不白的加了一个using namespace std;意思就是说代码中用到得cout对象是来自于std,但是我不知道的是在std中竟然也带有一个max()函数,那么我在调用max()函数时,就会因为std中有一个max()函数和我自己写的产生了冲突。编译错误列表里也作出了明确的说明: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int],亏我当时还想出了最原始的解决名字冲突的方法:把我自己写的函数max()换个别的名字,水死了。。。那么接下来我将using namespace std;去掉了是不是问题就解决了呢?编译一下,发现还是出错!错误是:`cout' undeclared (first use this function)。因为cout是在std命名空间下的一个对象,所以要用cout时必须要用std::cout才行。再次编译运行,成功了。那么如果我想用std空间下的max()该怎么办呢?很简单,只需:std::cout<<std::max(1,2);即可~

现在我们也可以稍微延伸一下,可以给自己的模板函数写命名空间,然后通过域操作符来调用这个max()函数了:

#include <iostream>
namespace nero
{
template <class T>
inline const T max(T a,T b)
{
       return a>b? a:b;
}
}
int main()
{
    std::cout<<nero::max(1,2);
    while(1);
    return 0;
}