玩转C++名字空间

一、概要

名字空间是一种描述逻辑分组的机制。也就是说,如果有一些声明按照某种准则在逻辑上属于同一个集团,就可以将它们放入同一个名字空间,以表明这个事实。名字空间就是为了表示逻辑结构。同时也避免了名字冲突。

名字空间的声明和定义:

namespace namespace-name {

}

PS:只有名字空间的声明定义与函数的定义后是不用分号;的,其余的都是要带分号的。

二、使用声明和使用指令

int main() {
	std::cout << "Hello World" << std::endl;
	std::cout << "Come On" << std::endl;
	return 0;
}

如果像上面那样写,很令人厌烦。有两种方式可以解决这种烦恼。

(1)使用声明:

int main() {
	using std::cout;
	using std::endl;
	cout << "Hello World" << endl;
	cout << "Come On" << endl;
	return 0;
}

使用声明,可以声明你想要的东西。

(2)使用指令

int main() {
	using namespace std;
	cout << "Hello World" << endl;
	cout << "Come On" << endl;
	return 0;
}

使用指令,则把该名字空间下的所有名字都变成可用的。 

全局性的使用指令是一种完成转变的工具,在其他方面最好避免使用。在一个名字空间里的使用指令是一种名字空间的组合工具。在一个函数里可以安全地讲使用指令作为一种方便的记法方式。


三、名字空间的组合

namespace Stack {
	void create();
	void push(char *data);
	char *pop();
	int length();
}   //在其他地方实现。

namespace Employee {
	using namespace Stack;
	void init() {
		create();
	}
	
	void insert(char *name) {
		push(name);
	}
	
	char* get_employee() {
		return pop();
	}
}
名字空间的组合也是一种设计,设计理念类似于类的组合。

四、多重界面

多重界面可以提供给用户不同的借口,而用户不用关心其底层是怎么实现的。

例子:

str1.h

#ifndef STR1_H_INCLUDED
#define STR1_H_INCLUDED
namespace My_String {
    void init();
    int length();
    void set_string(char *data);
    void print_string();
}


#endif // STR1_H_INCLUDED

str2.h

#ifndef STR2_H_INCLUDED
#define STR2_H_INCLUDED
namespace My_String {
    void init();
    int length();
}


#endif // STR2_H_INCLUDED

实现:strImpl.cpp

#include "str1.h"
#include <iostream>

namespace My_String {
char *buf = new char[200];
}

void My_String::init() {
    strcpy(My_String::buf,"hello world");
}
int My_String::length() {
    return strlen(My_String::buf);
}
void My_String::print_string() {
    std::cout << buf << std::endl;
}
void My_String::set_string(char *data) {
    char *tem = (char*)malloc(strlen(data) + 1);
    strcpy(tem,data);
    delete buf;
    buf = tem;
}


str1.h和str2.h使用的都是My_String的名字空间,但提供给外界的接口是不一样的。

测试:

#include <iostream>
#include "str1.h"    //包含的是str1

using namespace std;

int main() {
    My_String::init();
    char *pc = "my pc";
    My_String::set_string(pc);
    cout << My_String::length() << endl;
    My_String::print_string();
    return 0;
}
#include <iostream>
#include "str2.h"

using namespace std;

int main() {
    My_String::init();
    char *pc = "my pc";
    My_String::set_string(pc);   //错误,str2没提供这个接口
    cout << My_String::length() << endl;
    My_String::print_string();  //错误,str2没提供这个接口
    return 0;
}

五、无名名字空间与名字空间别名

有时,将一组声明包裹在一个名字空间里就是为了避免可能的名字冲突。这样做的目的只是保持代码的局部性,而不是为用户提供界面。

noname.h

namespace {
	int a;
	double f(){};
}

void g() {
	f();  
}

无名名字空间有一个隐含的使用指令的。上面的代码相当于。

namespace $$${
	int a;
	double f(){};
}
using namespace $$$;

void g() {
	f();  
}
但不能在noname.h之外使用到这个无名名字空间里的东西了。例如:

#include "noname.h"

void h() {
	a = 5;  //错误,a不是全局变量,已经被包含在无名的名字空间中了。
}

如果名字空间的名字太长,我们可以给他取个别名。

例如:

namespace SomeOne_Union_Shit {
	char *shit;
	.....
}

namespace SomeOne = SomeOne_Union_Shit;
SomeOne::shit = "hello";

六、组合与选择

namespace His_lib {
	void f() { cout << "his f"  << endl; }
	void g() { cout << "his g" << endl; }
}

namespace Her_lib {
	void f() { cout << "her f"  << endl; }
	void g() { cout << "her g" << endl; }
}

namespace My_lib {
	using namespace His_lib;
	using namespace Her_lib;
	
	using His_lib::f;   //偏向His_lib的方式解析潜在的冲突
	using Her_lib::g;	//偏向Her_lib的方式解析潜在的冲突
	
	void h() {
		f();   // his f
		g();   // her g
	}
	
}

七、名字空间与重载,以及其开放性。

重载可以跨名字空间工作的。

namespace His_lib {
	void f(int i) { cout << "his f" << endl; }

}

namespace Her_lib {
	void f(char c) { cout << "her f"  << endl; }

}

namespace My_lib {
	void g() {
		f(3); //his f
		char c = 'a';
		f(a);  //her f
	}
	
}

名字空间是开放的。一个名字空间的定义可以分布到多个头文件和源代码文件里。名字空间的开放性使我们可以通过展示名字空间不同部分的方式,为不同种类的用户提供不同的界面。

head1.h

namespace His_lib {
	void f() ;
}

head2.h

namespace His_lib {
	void g() ;
}

如果你只是向在文件里实现原先名字空间中已经声明的函数,则最好在此之前用名字空间的名字去修饰使用His_lib::的方式。

#include "head1.h"
namespace His_lib {
	void His_lib::ff() {}  //编译错误,His_lib没有声明这个。
	void ff() {} //编译通过,在名字空间His_lib中引用了新的ff函数

}


总结:

一个名字空间应该:

[1]描述了一个具有逻辑统一性的特征集合。

[2]不为用户提供对无关特征的访问,使用封装。

[3]不给用户强加任何明显的记述负担。


参考书籍《C++程序设计语言》



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值