Aoki Job Seeker

C++命名空间及using相关用法总结

2019-03-16
C++

C++命名空间及using相关用法总结

1.C++命名空间(namespace)


在C++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象。工程越大,名称相互冲突性的可能性越大。另外,在使用多个厂商的类库时,也可能导致名称冲突。为了避免冲突,在大规模的设计中,以及程序员使用1各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namesapce(命名空间/名字空间/名称空间),可以更好的控制标识符得到作用域。

#include <iostream>
using namespace std;


//创建一个命名空间
namespace study
{
	int a = 10;
}

namespace learn
{
	int a = 20;
}
int main()
{
	cout << "命名空间study的a="<<study::a << endl;
	cout <<"命名空间learn的a="<< learn::a << endl;
}

运行结果输出:

在命名空间下,可以定义函数,变量、结构体、类;除此之外,对于命名空间的定义还应当注意,它必须定义在全局作用域下。

#include <iostream>
#include<string>
using namespace std;


namespace study
{
	int a = 10;
	namespace A
	{
		int a = 100;
		void sayhi()
		{
			cout << "hi,Aoki" << endl;
		}
		struct Student
		{
			string name;
		};
	}
}

namespace learn
{
	int a = 20;
}
int main()
{
	//cout << "命名空间study的a="<<study::a << endl;
	//cout <<"命名空间learn的a="<< learn::a << endl;
	study::A::sayhi();
	cout << "作用域A下的a=" << study::A::a << endl;

}

输出结果:

下面是对命名空间错误定义的举例:

对于命名空间,我们还可以定义无名命名空间,意味着命名空间中的标识符只能在本文件中访问,相当于给这个标识符加上了static,使得其可以作为内部连接。
除此之外,还有就是给命名空间起别名,我们为命名空间A起别名为b,源码如下:

#include <iostream>
#include<string>
using namespace std;


namespace A
{
	int a = 100;
	void test()
	{
		namespace b = A;//给命名空间起别名为b
		cout <<"A作用域内a="<< b::a << endl;
	}
}
namespace //无名(匿名)命名空间
{
	int c = 15;
	int d = 16;
}

int main()
{
	cout << "c=" << c << endl;
	cout << "d=" << d << endl;
	A::test();
}

运行结果如下图:

下面对命名空间namespace的用法总结如下:

  • 命名空间的用途:解决名称冲突问题
  • 命名空间下可以定义函数、变量、结构、类
  • 命名空间必须定义在全局作用域下
  • 命名空间可以嵌套命名空间
  • 命名空间是开放的,可以随时给原先的命名空间添加内容
  • 定义另个名字相同的命名空间时,两个命名空间会合并,但是不会覆盖
  • 当我们定义了无名空间时,相当于写了static intc=15,static int d=16,只能在当前文件内使用

2.using声明


using声明可使得指定的标识符可用

#include <iostream>
using  namespace std;


namespace One
{
	int test = 100;
}

void  test()
{
	int test = 100;
	using One::test;//using声明
	cout << "test=" << test << endl;
}


int main()
{
	test();
}

此处我们使用了using声明,但是编译却发生了错误。因为在test()中我们定义了一个整型数test,并赋予了初值。当我们使用using声明时,编译器有就近原则,它会选择输出test中定义的整型数,但是又发现有using声明,出现二义性问题,编译器不知道怎么处理,所以报错。报错信息如下:

所以,在using声明中,我们应当注意避免二义性问题。

#include <iostream>
using  namespace std;


namespace One
{
	int test = 100;
}

void  test()
{
	int test = 100;
	//using One::test;//using声明
	cout << "test=" << test << endl;
}


int main()
{
	test();
}

输出结果如下图:

using声明的一个例子:

#include <iostream>
using  namespace std;


namespace One
{
	int test = 100;
	int a = 99;
	int b = 30;
	void func()
	{
		cout << "hi,Aoki!" << endl;
	}
	void func1()
	{
		cout << "hello,Aoki!" << endl;
	}
}

void  test()
{
	cout << "test=" << One::a << endl;
	//using声明
	using One::a;
	using One::func1;
	using One::func;
	cout << "a=" << a << endl;
	func1();
	func();
}


int main()
{
	test();
}

运行结果如下图:

下面是using声明遇到函数重载的一个例子:

#include <iostream>
using  namespace std;

namespace Two
{
	void func()
	{
		cout << "Nothing!" << endl;
	}
	void  func(int x)
	{
		cout << x << endl;
	}
	void func(int x, int y)
	{
		cout << "x=" << x ;
		cout << ",y=" << y << endl;

	}
}
void test1()
{
	using Two::func;
	func();
	func(15);
	func(15, 20);
}


int main()
{
	test1();
}

输出结果如下图:

如果命名空间包含一组用相同名字重载的函数,using声明就声明了这个重载函数的所有集合。

3.using编译指令


using编译指令使整个命名空间标识符可用。

#include <iostream>
using  namespace std;


namespace One
{
	int a = 99;
	int b = 30;
	void func()
	{
		cout << "hi,Aoki!" << endl;
	}
	void func1()
	{
		cout << "hello,Aoki!" << endl;
	}
}

void  test()
{
	using namespace One;
	cout << a << endl;
	cout << b << endl;
	func();
	func1();
	int a = 100;//没有产生二义性
	cout << a << endl;
}
namespace Two
{
	int a = 1;
	int b = 2;
};
void test1()
{
	//产生二义性
	using namespace One;
	using namespace Two;
	cout << a << endl;
}

当我们像上面一样使用using编译指令时,会出现二义性问题,编译器无法通过编译。错误信息如下:

当我们使用using声明或using编译指令时,会增加命名冲突的可能性。也就是说,如果有命名空间,并在代码中使用作用域解析运算符,则不会出现二义性问题。
例子如下:

#include <iostream>
using  namespace std;


namespace One
{
	int a = 99;
	int b = 30;
	void func()
	{
		cout << "hi,Aoki!" << endl;
	}
	void func1()
	{
		cout << "hello,Aoki!" << endl;
	}
}

void  test()
{
	using namespace One;
	cout << a << endl;
	cout << b << endl;
	func();
	func1();
	int a = 100;
	cout << a << endl;
}
namespace Two
{
	int a = 1;
	int b = 2;
};
void test1()
{
	using namespace One;
	using namespace Two;
	//cout << a << endl;
}


int main()
{
	test();
	test1();
}

输出结果如下:

当我们引入一个全局的using编译指令时,就为该文件打开了命名空间,它不会影响其他的文件,所以可以再每一个实现文件中调整对命名空间的控制。比如,如果发现某一个实现文件中有太多using指令而产生命名冲突,就要对该文件做个简单的改变,通过明确限定或者using声明来消除名字冲突,这样不需要修改其他实现文件。






The End



上一篇 初探C#

Comments

Content