http://longsy.iteye.com/blog/353019
命名空间的作用:避免名字冲突和解决命名空间污染问题
命名空间的定义
namespace namespace_name {
//declarations
}
例:
- /*
- file:my.h
- author:longsy
- */
- //declare namespace My_lib
- namespace My_lib {
- void describe();
- }
一般命名空间的声明放在头文件中,而实现则放在源文件中
命名空间也是一个作用域,实现命名空间的函数时,要使用作用域操作符(::)
- /*
- file:my.c
- author:longsy
- */
- #include "my.h"
- void My_lib::describe()
- {
- //do something...
- }
引入某入命名空间的方法
1.using 声明
- /*I have defined my namespace in the file named "my.h"
- and I also have implemented the namespace in the "my.c"
- */
- /*
- file:test1.c
- author:longsy
- */
- #include "my.h"
- //using声明,引入describe函数,只需要引入名字,不需要带括号和参数
- using My_lib::describe; //也可以将该语句放入函数中
- void test1()
- {
- describe(); //My_lib::describe();
- }
2.using 指令
- /*I have defined my namespace in the file named "my.h"
- and I also implemente the namespace in the "my.c"
- */
- /*
- file:test2.c
- author:longsy
- */
- #include "my.h"
- //using指令,引入My_lib空间中的所有名字
- using namespace My_lib; //也可以将该语句放入函数中
- void test2()
- {
- describe(); //My_lib::describe();
- }
一个命名空间是可以分散在多个文件中,在不同文件中的命名空间定义是累积的
向一个已存在命名空间引入新的成员
#include "my.h" //先引入命名空间所声明的头文件
namespace My_lib {
//new members...
}
无名命名空间: 将命名空间局限于一个文件中
namespace {
//declarations
}
在同一个文件中可以直接使用无名命名空间的名字而无需使用作用域操作符或者using声明和指令
命名空间的嵌套 :可以在一个命名空间中声明另一个命名空间
例:
- namespace A{
- int i; //A::i
- int j;
- namespace B{
- int i;
- int k=j;//A::j
- } //end of B scope
- int h = i; //A::i
- } // end of A scope
引用嵌套里的名字时,使用多层作用域操作符
using A::B::k;
或 using namespace A::B;
命名空间别名: 一般是为了方便使用,给较长的命名空间取一个较短的命名空间来使用
取别名的语法:
namespace 源空间名 = 别名;
能使用别名来访问源命名空间里的成员,但不能为源命名空间引入新的成员
命名空间函数重载: 如果从多个命名空间里引入同名而不同参的函数,且它们满足构成重载的条件,则构成重载
例:
- //a.h
- namespace A{
- void f(char) {//...}
- }
- //b.h
- namespace B{
- void f(int) {//...}
- }
- //test.c
- #include "a.h"
- #include "b.h"
- void test()
- {
- using A::f;
- using B::f;
- f('a');//A::f(char)
- f(10);//B::f(int)
- }
http://blog.sina.com.cn/s/blog_9f1c0931010187y3.html
在使用任何名字空间之前,编译器必须能够找到他,即确定他的声明所在的作用域。使用某个名字空间中的名字最简单的方式就是使用限定名字,即把名字空间的名字(如numeric)作为前缀,然后加上作用域操作符(::)。
然而又是可能不愿使用名字空间以追求代码简洁。可以通过下面实现:
1.使用using指令
如:using namespace std;
语法:关键字using,关键字namespace,一个名字空间名字。using指令指导编译器把该名字空间的名字视为全局一般对待。
2.使用using声明
如:using numeric::rational;
比起using指令,使用using声明会更加具体,从而减少了危险性。using声明将另一个名字空间中的某个名字引入到局部作用域中。
using声明将名字加入到局部作用域中,起到同显示声明它一样的效果。因此,在使用using声明的作用域内使用被声明的名字时不需要加上限定(如rational)。
3.对比using指令与using声明
#include <iostream>
#incldue <ostream>
void demonstrate_using_directive()
{
using namespace std;
typedef int ostream;
ostream x(0);
std::cout<<x<<"\n";
}
void demonstrate_using_declaration()
{
using std::ostream;
typedef int ostream;
ostream x(0);
std::cout<<x<<'\n';
}
局部变量ostream和using声明冲突,但和using指令不冲突。对于一个名字,一个局部作用域中只能有一个对象或类型使用该名字,而using声明会把该名字加入到该局部作用域中,但using指令不会。
4.类中的using声明
using声明也可以引入类的某个成员,和名字空间的using声明不同,不能随意向任何存在的类引入任何存在的成员,但是可以向某个派生类引入其积累的某个名字。在几种场合中需要使用它,常见的有如下两个:
1)基类声明了某个函数,其派生类也声明了一个同名函数,且希望能通过重载找到这两个函数。编译器只会在单一的类作用域中寻找重载,使用using声明将基类函数引入派生类作用域,则在处理重载时,就会在派生类作用域中查找这两个函数,并选出最佳匹配项。
2)在私有继承时,通过在派生类的公有段使用using声明,可以有选择地公开一些成员。
例:
#include <iostream>
#incldue <ostream>
class base
{
public:
void print(int i)
{
std::cout<<"base:"<<i<<"\n";
}
};
class derived1:public base
{
public:
void print(double d)
{
std::cout<<"derived:"<<i<<"\n";
}
};
class derived2:public base
{
public:
using base::print;
void print(double d)
{
std::cout<<"derived:"<<i<<"\n";
}
};
int main()
{
derived1 d1;
derived2 d2;
d1.print(42);
d2.print(42);
}
输出:
derived:42
base:42