在一个企业级的开发中,一个工程往往会很大,定义的类和方法也会特别多,而且还会引入很多的第三方库,这就不可避免的会有一些同名的冲突问题。在Java中有包(Package)的概念,也就是将不同功能的类分成不同的包,来解决名称的冲突,C++中是用命名空间来解决这种冲突的。
什么是命名冲突
假设你的程序中有一个第三方库ThirdLib.lib,里面有一个全局的函数 void HelloWorld();你又在自己的工程中再次定义一个HelloWorld(),则会有命名冲突。
再比如,一个大的工程有多个人同时开发,每个人开发一个模块,其中有A模块和B模块分别有甲、乙两个人开发。假设A模块有一个struct结构Node,B模块也有一个struct结构Node,由于是两个人开发,A中的Node和B中的Node虽然名字相同但结构却不同。如果A、B两个模块都没有命名空间就会发生冲突,因为同一个作用域内不能有两个同命的类。
像这样导致命名冲突的情况还有很多,总结来说就是在相同的作用域内出现多个同名的类、函数或变量。
定义命名空间
【例1】
Hello.h
#pragma once
namespace SH
{
class Hello
{
public:
Hello(void);
~Hello(void);
public:
void SayHello();
};
void HelloWord();
}
Hello.cpp
#include "StdAfx.h"
#include "Hello.h"
#include <iostream>
using std::cout;
using std::endl;
namespace SH
{
Hello::Hello(void)
{
}
Hello::~Hello(void)
{
}
void Hello::SayHello()
{
cout << "how are you!" << endl;
}
void HelloWord()
{
cout << "Hello World!" << endl;
}
}
Hello.cpp还可以定义成这样:
SH::Hello::Hello(void)
{
}
SH::Hello::~Hello(void)
{
}
void SH::Hello::SayHello()
{
cout << "how are you!" << endl;
}
void SH::HelloWord()
{
cout << "Hello World!" << endl;
}
【例2】命名空间的定义也可以是不连续的,如:
Hello.h
#pragma once
namespace SH
{
class Hello
{
public:
Hello(void);
~Hello(void);
public:
void SayHello();
};
}
void HelloWord();
namespace SH
{
void Hello2Sunly();
}
Hello.cpp
#include "StdAfx.h"
#include "Hello.h"
#include <iostream>
using std::cout;
using std::endl;
SH::Hello::Hello(void)
{
}
SH::Hello::~Hello(void)
{
}
void SH::Hello::SayHello()
{
cout << "how are you!" << endl;
}
void HelloWord()
{
cout << "Hello World!" << endl;
}
void SH::Hello2Sunly()
{
cout << "Hello Sunly!" << endl;
}
上面的例子中类Hello和函数Hello2Sunly的命名空间相同,都是SH。HelloWord并没有在SH命名空间上,是在默认的全局命名空间内。
使用命名空间
加命名空间的前缀和作用域运算附
#include "stdafx.h"
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
这种方式最安全,因为使用的每个变量都用命名空间的前缀指明了具体的版本。但比较麻烦,因为每次使用都要加前缀。
using声明
#include "stdafx.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
需要哪个变量时就声明哪个变量,这种方式相对较安全,也不至于太麻烦,只推荐的一种方式。用using引入的变量,其作用域从using指示开始一直到using指示所在的作用域结束。
using 指示
#include "stdafx.h"
#include <iostream>
#include "Hello.h"
using namespace std;
using namespace SH;
int main()
{
cout << "Hello World!" << endl;
Hello2Sunly();
return 0;
}
这种方式将某一命名空间下的所有变量都注入进来了,这种方式使编程更简单了,不用把需要用到的变量一个一个地用using加进来,但又再次带来了命名冲突的危险,因为多个命名空间都提到当前的作用域下,又有可能发生重名的问题。