您的位置:首页 > 编程语言 > C语言/C++

C++名字空间详解

2017-04-18 10:33 218 查看
本质的目的:代码量增加后,不同名字空间内的同名函数、同名变量等可以同时存在,互不冲突

作用的结果:在名字空间中声明和定义的内容都属于这个名字空间

语法格式:

namespace 名字空间名
{
//名字空间内的声明和定义
} ;


范例:

namespace zhangsan    //名字空间zhangsan
{
    class Student
    {
    public:
        int age;
    };
};

namespace lisi    //名字空间lisi
{
    class Student
    {
    public:
        int age;
    };
};
    
class Student    //如果没有说明在哪个名字空间,则默认在全局名字空间
{
public:
    int age;
};

using namespace std;
int main()
{
    zhangsan::Student stuZ;    //声明一个类型为zhangsan::Student的变量
    stuZ.age = 12;    //这时使用的是zhangsan名字空间下的Student类
    cout<<stuZ.age<<endl;
    
    ::Student stuM;    //如果没有指明名字空间,则默认为全局名字空间
    stuM.age = 13;
    cout<<stuM.age<<endl;
    
    return 0;
}
以上可看到,虽然都有class Student,但在不同的名字空间中,不会产生冲突。在这些同名的类前加上相应的名字空间来限制,从而访问在某个名字空间下所定义的具体的某个类。当然,如果没有指明名字空间,则默认为全局名字空间,也称为匿名名字空间。



namespace zhangsan	//名字空间zhangsan
{
class Student	//有重名
{
public:
int age;
};

class Teacher	// 独一无二
{
public:
int age;
bool male;
};
};

namespace lisi	//名字空间lisi
{
class Student	//有重名
{
public:
int age;
};
};

class Student	//如果没有说明在哪个名字空间,则默认在全局名字空间 (有重名)
{
public:
int age;
};

#include <iostream>
using namespace zhangsan;	//设置默认查找名字空间为张三,除非指定名字空间限制,否则每次都从默认名字空间中查找
int main()
{
//Student stu1;	//error! 因为默认空间zhangsan的Student和全局(匿名空间)中的Student重名,编译器不知道用哪个
//stu1.age = 1;

::Student stu2;	//right! 用的是默认空间zhangsan的student
stu2.age = 2;
lisi::Student stu3;	//right! 用的是lisi名字空间的student
stu3.age = 12;

Teacher t1;
t1.male = true;	//right! 虽然没有指定名字空间,但Teacher独一无二,所以编译器在默认zhangsan中找没有之后,能够独一无二的找到Teacher

return 0;
}
在开发实践中,常常将不同的模块划分为不同的名字空间,这样各个模块内部声明的函数、数据等不会互相影响,名字空间起到了很好的模块包装的作用

#include<iostream.h>   是C语言中比较通用的(加.h就不用using namespace)

#include<iostream> 

using namespace std;    是C++中比较通用的

namespace是为了解决C++中的名字冲突而引入的。什么是名字冲突呢?比如,在文件x.h中有个类MyClass,在文件y.h中也有个类MyClass,而在文件z.cpp中要同时引用x.h和y.h文件。显然,按通常的方法是行不能的,那怎么办呢?引入namespace即可。例如:    

// x.h
namespace MyNamespace1
{
class MyClass
{
public:
void f();
private:
int m;
}
};

在y.h中的内容为
// y.h
namespace MyNamespace2
{
class MyClass
{
public:
void f();
private:
int m;
}
};

然后在z.cpp中引入x.h和y.h
// z.cpp
#include"x.h"
#include"y.h"

void z::f()
{
//声明一个文件x.h中类MyClass的实例x
MyNamespace1::MyClass x;
//声明一个文件x.h中类MyClass的实例x
MyNamespace2::MyClass y;

//调用文件x.h中的函数f
x.f();
//调用文件y.h中的函数f
y.f();
}


 名字空间实质上是一个作用域。通过上面的一个实例应该就明白名字空间的作用了

今天突然看到一个这样的说法,很多时候使用这句代码不是一个好的办法:

using namespace std;


更加合适的做法是使用诸如:

std::cout以及std::cin。

为什么呢?是因为性能的原因吗?

std::cout以及std
4000
::cin。是使用系统定义的cout和cin方法且仅使用这两个方法,using namespace std则是将所有的系统定义的标识符导入,也就是说你自己定义的东西(变量,方法,类等)不能和系统中的这些标识符重名,否则将出现命名冲突的错误!

所谓namespace,是指标识符的各种可见范围。 

C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。 由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择: 

1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下:

#include <iostream>

int main()
{
std::cout<<"sadasd"<<std::endl;
return 0;
}


2、使用using关键字。

#include <iostream>
using std::cout;
using std::endl;

int main()
{
    cout<<"sadasd"<<endl;
    return 0;
}


3、最方便的就是使用using namespace std; 

#include <iostream>
using namespace std;

int main()
{
cout<<"sadasd"<<endl;
return 0;
}


这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。

因为标准库非常的庞大,所程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准 库中的一切都被放在名字空间std中。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。

明白了为什么出现这个错误我们就改写代码如下:
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

template <typename T>
T max (T a,T b)
{
return ((a>b)?a:b);
}
int main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}
这是比较推荐的做法,因为C++ PRIMER, EFFECTIVE C++上都是用这种方式的,但是谭浩强的书上都是一句using namespace std;就搞定,这在有些情况中会出现错误。其实还有两个简单的解决方案,那就是把自己定义的函数改成其他的名字,或者直接用微软提供的函数。相信微软提供的效率绝对不会比我们写的低
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: