以下内容为大学期间学习C++语言总结的知识:
《C++》基础入门_01——数据存储,表示形式,基本运算
《C++》基础入门_02——面向对象的总体概括
《C++》基础入门_03——程序的开发过程
《C++》基础入门_04——四大语句
《C++》基础入门_05——函数详解篇
《C++》基础入门_06——面向对象的详述
《C++》基础入门_07——数据的共享保护:const
《C++》基础入门_08——利用数组实现对批量数据的处理
《C++》基础入门_09——指针和引用的讲解
《C++》基础入门_10——用户自定义数据类型详细篇
《C++》基础入门_11——友元的讲解
《C++》基础入门_12——类模板
《C++》基础入门_13——运算符的重载
《C++》基础入门_14——继承与派生
《C++》基础入门_15——多态性
《C++》基础入门_16——输入输出流详讲
《C++》基础入门_17——对象串行化
《C++》基础入门_18——异常处理
《C++》基础入门_19——命名空间
《C++》基础入门_20——文件操作
《C++》基础入门_21——在函数中返回数组的常用方法
在以往的程序中,我们发现都有一句语句:
using namespace std;
此句话就使用了命名空间std。
一、为什么需要命名空间
- 命名空间是ANSI c++引入的用户命名的作用域,用来处理程序中常见的同名冲突。
- C语言中引入了3个层次的作用域:
文件(编译单元)、函数、复合语句
c++又引入了类作用域,类是出现在文件内的。
下面我们先来分析一下作用域的作用:
-
若在文件中定义了两个类,这两个类中可以定义同名的函数。引用时,加上类名作为限定即可。
#include <iostream> #include<string> using namespace std; class Student { public : void fun1() { cout << "Student::fun1()" << endl; } }; class Teacher { public: void fun1() { cout << "Teacher::fun1()" << endl; } void fun2() { cout << "Teacher::fun2()" << endl; } }; void main() { Student s; Teacher t; s.fun1();//Student::fun1() t.fun1();//Teacher::fun1() }
-
全局变量的作用域是整个程序。若一个程序包含文件A和文件B,在A文件和B文件分别定义了全局变量a,在两文件进行连接时会出现错误,因为有两个同名变量,系统会认为是重复定义的变量。可以通过加某一个文件内对全局变量a加extern,声明一段程序中两个同名变量是同一变量。
-
一个大型应用软件一般多人开发,若不同的人定义自己的类,放入不同头文件里,在主文件使用这些类时,使用#include指令把这些头文件包含进来。但是不同的头文件有不同的人设计的,很可能发生同名函数或类。程序会发生错误。
head.h文件:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
Student(int n,string na) {
sno = n;
name = na;
}
void getDate();
private:
int sno;
string name;
};
void Student::getDate() {
cout << "Student :" << name << " " << sno << endl;
}
double fun(double a,double b) {
return a + b;
}
head1.h文件:
#pragma once
#include <string>
#include<iostream>
using namespace std;
class Student {
public:
Student(int n,string na) {
sno = n;
name = na;
}
void getDate();
private:
int sno;
string name;
};
void Student::getDate() {
cout << "name: "<<name << "sno: " << sno << endl;
}
double fun(double a,double b) {
return a + b;
}
主文件(.cpp):
#include <iostream>
#include "head.h"
#include "head1.h"
#include<string>
using namespace std;
void main() {
Student stu(1001, "Tom");
stu.getDate();
cout << fun(5.7, 5);
}
进行编译:
出错:名字冲突
- 不同的库中包含相同实体名,编译时会出现名字冲突,称为:全局命名空间污染。
- C语言和早期c++未解决此问题。
二、什么是命名空间
为了解决以上问题,ANSI C++增加了命名空间。所谓命名空间,实际上是由程序设计者命名的内存区域。程序设计者根据自己的需求指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分割开。
- 一个命名空间将不同的标识符集合在一个命名作用域(named scope)内为了解决命名冲突
- 没有声明命名空间的标识符都处于无名的命名空间中
例如,声明一个命名空间NS:
namespace NS {
class File;
void Fun ();
}
则引用标识符的方式如下,
NS:: File obj;
NS:: Fun ();//被限定名
- namespace 是定义命名空间所必须的关键字。
- 花括号内是声明快,在其中声明的实体称为命名空间成员。
- 使用块内的变量需要加上命名空间名加作用域分辨符::,称为命名空间限定。
- 声明一个命名空间是的花括号里可以包含的内容:
- 变量(可以带初始化)
- 常量;
- 函数(可以是声明或定义)
- 结构体
- 类
- 模板
- 命名空间(嵌套定义)
三、使用命名空间成员的方法
- 引用的一般形式:
命名空间名::命名空间成员名 - c++提供了一些机制,能简化使用命名空间中的成员的手续
-
使用命名空间别名
可以为命名空间起一个别名,用来代替较长的命名空间名。namespace Television
{·····}
namespace TV=Television; -
使用“using 命名空间成员名”
using 后面的命名空间成员名必须是由命名空间限定的名字。
若使用“using 命名空间名”一次只能声明一个命名空间成员,若在一个命名空间中定义了10个实体,就使用10次using命名空间成员名。using nsl::Student;
以上语句声明:在本作用域中会用到命名空间nsl中的成员Student,在本作用域中若使用该命名空间成员时,不必再逐个用命名空间名限定。
using声明的有效范围是从using开始到using所在的作用域结束。using nsl::Student;
using ns2::Student;
会产生二义性。 -
使用“using namespace 命名空间名”
一般格式:using namespace 命名空间名;using namespace snl;
声明在本作用域中要用到命名空间nsl的成员,在使用nsl的任何成员时都不需要在使用命名空间限定。
若同时用using namespace 定义多个命名空间时,易出错。
-
四、无名的命名空间
前面介绍的都是有名字的命名空间,C++还允许使用没有名字的命名空间。
文件A中:
namespace {
void fun(){ coout << "jsdj" << endl; } fun()函数只在文件A中有效。
}
由于没有名字,在其他文件无法引用,它只在本作用域内有效。
C语言中提供static声明一个函数,其作用是使函数只能作用于本文件。c++保留了static,并通过无名空间实现的。
五、标准命名空间std
- 标准C++库的所有标识符都是在一个名为std的命名空间中定义的。或者说标准头文件中的函数、类、对象和类模板是在命名空间std中定义的。
- std是standard的缩写,表示这是存放标准库的有关内容的命名空间。
- using namespace std;在std中定义的所有标识符在本文件中都可作为全局变量来使用。
六、使用早期的函数库
- C++从C语言继承了很多函数库,在c++中可以使用C语言的函数库。
- 若用库中的函数,则需要在程序文件中包含有关的头文件,在不同的头文件中,包含不同的函数声明。
- c++中使用这些头文件有二种方法:
-
用C语言程序中使用的传统老方法。头文件后缀包含.h.
c语言中无命名空间,在c++中若用带.h的头文件,不需要使用命名空间。例如:#include <math.h>
-
用c++新方法。c++标准规定头文件不含后缀.h。
为了表示与c的头文件有联系又有区别。c++的头文件名在C语言相应的头文件(不含.h)之前加字母c。
需要使用命名空间。
-