命名空间

命名空间

# 命名空间image-20240101150131801# 为什么要使用命名空间?一个大型的工程往往是由若干个人独立完成的,不同的人分别完成不同的部分,最后再组合成一个完整的程序。由于各个头文件是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数,这样在程序中就会出现名字冲突。不仅如此,有可能我们自己定义的名字会与C++库中的名字发生冲突。

名字冲突就是在同一个作用域中有两个或多个同名的实体,为了解决 ,C++中引入了命名空间,所谓命名空间就是一个可以由用户自己定义的作用域,在不同的作用域中可以定义相同名字的变量,互不干扰,系统能够区分它们。

# 什么是命名空间命名空间又称为名字空间,是程序员命名的,程序员根据需要指定一些有名字的空间域,把一些全局实体分别存放到各个命名空间中,从而与其他全局实体分隔开。通俗的说,每个名字空间都是一个名字空间域,存放在名字空间域中的全局实体只在本空间域内有效。名字空间对全局实体加以域的限制,从而合理的解决命名冲突。

# 基本格式C++中定义命名空间的基本格式如下:

namespace wd

{

int val1 = 0; //不需要table,直接正常顶格写

char val2;

}// end of namespace wd //不需要写;

不需要写;,写了相当于执行一句空语句

# 存放的类型在声明一个命名空间时,大括号内不仅可以存放变量,还可以存放以下类型:

常量变量函数,可以是定义或声明结构体类模板命名空间,可以嵌套定义 namespace wd

{

int number = 0;

struct Foo

{

char ch;

int val;

};

void display();

}// end of namespace wd

# 可见域定义在名称空间中的变量或者函数都称为实体,名称空间中的实体作用域是全局的, 并不意味着其可见域是全局的。

如果不使用作用域限定符和using机制,抛开名称空间嵌套和内部屏蔽的情况,实体的可见域是从实体创建到该名称空间结束。在名称空间外,该实体是不可见的。# 命名空间的使用方式命名空间一共有三种使用方式,分别是using编译指令、作用域限定符、using声明机制

# using编译指令我们接触的第一个C++程序基本上都是这样的,其中std代表的是标准命名空间。

#include

using namespace std; //using编译指令

int main(int argc, char *argv[])

{

cout << "hell,world" << endl;

return 0;

}

其中第二行就使用了using编译指令。如果一个名称空间中有多个实体,使用using编译指令,就会把该空间中的所有实体一次性引入到程序之中;对于初学者来说,如果对一个命名空间中的实体并不熟悉时,直接使用这种方式,有可能还是会造成名字冲突的问题,而且出现错误之后,还不好查找错误的原因,比如下面的程序就会报错,当然该错误是人为造成的。

#include

using namespace std;

double cout() //error 代码二义性

{

return 1.1;

}

int main(void)

{

cout(); //error 代码二义性

return 0;

}

# 作用域限定符第二种方式就是直接使用作用域限定符::啦。每次要使用某个名称空间中的实体时,都直接加上,例如:

namespace wd

{

int number = 10;

void display()

{

//cout,endl都是std空间中的实体,所以都加上'std::'命名空间

std::cout << "wd::display()" << std::endl;

}

}//end of namespace wd

int main(void)

{

std::cout << "wd::number = " << wd::number << endl;

wd::display();

}

这种方式会显得比较冗余,所以还可以采用第三种使用方式。

# using声明机制👍using声明机制的作用域是从using语句开始,到using所在的作用域结束。。

#include

using std::cout; //using声明机制

using std::endl;

namespace wd

{

int number = 10;

void display()

{

cout << "wd::display()" << endl;

}

}//end of namespace wd

using wd::number;

using wd::display;

int main(void)

{

cout << "wd::number = " << number << endl;

创建全局变量和全局函数的时候:

将自己的全局变量和全局函数放到# 匿名命名空间命名空间还可以不定义名字,不定义名字的命名空间称为匿名命名空间。由于,该空间中的实体,,它只能在本文件的作用域内有效,它的作用域是从匿名命名空间声明开始到本文件结束。在本文件使用无名命名空间成员时不必用命名空间限定。其实匿名命名空间和static是同样的道理,都是只在本文件内有效,无法被其它文件引用。

namespace {

int val1 = 10;

void func();

}//end of anonymous namespace

在匿名空间中创建的全局变量,具有全局生存期,却只能被本文件空间内的函数等访问,。

匿名命名空间的本质是什么?就是将命名空间的名字符号给去掉,让其他文件找不到。

C++ 新的标准中提倡使用匿名命名空间,而不推荐使用static,因为static用在不同的地方,涵义不同,容易造成混淆。另外,static不能修饰class。

# 命名空间的嵌套及覆盖int number = 1;

namespace wd

{

int number = 10;

namespace wh //嵌套

{

int number = 100;

void display()

{

cout << "wd::wh::display()" << endl;

}

}//end of namespace wh

void display(int number)

{

cout << "形参number = " << number << endl; //20

cout << "wd命名空间中的number = " << wd::number << endl; //10

cout << "wh命名空间中的number = " << wd::wh::number << endl; //100

cout << "全局number = " << ::number << endl; //1

}

}//end of namespace wd

int main(void)

{

using wd::display;

display(20);

return 0;

}

# 对命名空间的思考和总结下面引用当前流行的名称空间使用指导原则:

提倡已命名的,而不是直接定义外部全局变量或者静态全局变量。如果开发了一个或者,提倡将其放在一个名称空间中。对于using 声明,首先将其作用域设置为局部而不是全局(临近使用的地方声明)不要在头文件中使用using编译指令,这样,使得可用名称变得模糊,容易出现二义性,包含头文件的顺序可能会影响程序的行为,如果非要使用using编译指令,建议放在所有#include预编译指令后。# 课内代码#include

using namespace std;

#if 0 //注释方法

void HWprint()

{

}

void HFCPPProjectPrint()

{

}

#endif

namespace wd

{

//命名空间中可以定义变量、函数、结构体、命名空间,统称为实体

int number = 10;

void print()

{

cout << "void print()" << endl;

}

}//end of namespace wd

/* ; */

int main(int argc, char **argv)

{

cout << "number = " << wd::number << endl;//作用域限定符

wd::print();

return 0;

}

#include

using namespace std;//1、using编译指令,可以将命名空间中的实体全部引出来

//自定义的实体与命名空间中的实体冲突

int cout()

{

return 10;

}

int main(int argc, char **argv)

{

cout();

return 0;

}

#include

/* using namespace std;//1、using编译指令,可以将命名空间中的实体全部引出来 */

namespace wd

{

//命名空间中可以定义变量、函数、结构体、命名空间,统称为实体

int number = 10;

void print()

{

std::cout << "void print()" << std::endl;

}

}//end of namespace

//2、命名空间+作用域限定符的形式,即使自定义的实体命名空间中的

//实体冲突,一样没有影响

void cout(int x, int y)

{

std::cout << "x = " << x << ", y = " << y << std::endl;

}

int main(int argc, char **argv)

{

std::cout << "number = " << wd::number << std::endl;//作用域限定符

wd::print();

cout(3, 5);

return 0;

}

/*using 声明机制*/

#include

using std::cout;//3、using声明机制,一次只引出一个实体

using std::endl;//推荐使用这种

namespace wd

{

//命名空间中可以定义变量、函数、结构体、命名空间,统称为实体

int number = 10;

void print()

{

cout << "void print()" << endl;

}

}//end of namespace

int main(int argc, char **argv)

{

cout << "number = " << wd::number << endl;//作用域限定符

wd::print();

return 0;

}

/*命名空间是可以进行扩展的,结构体是不能进行扩展的*/

#include

using std::cout;

using std::endl;

//标准命名空间可以进行扩展

//有可能会与std中的实体冲突,一般不建议进行扩展(标准命名空间中的实体一般都是小写)

namespace std

{

struct MyStruct

{

int ia = 0;

};

}//end of namespace std

#if 0

//结构体是不能进行扩展的

struct A

{

int ia;

};

struct A

{

int ib;

};

#endif

//命名空间是可以进行扩展的

//带命名空间的函数声明

namespace wd

{

void print();

}

namespace hb

{

int number = 20;

void show()

{

cout << "void show()" << endl;

}

void display()

{

cout << "void display()" << endl;

wd::print();

}

}//end of namespace hb

namespace wd

{

int number = 10;

void print()

{

cout << "void print()" << endl;

hb::show();

}

}//end of namespace

int main(int argc, char **argv)

{

cout << "number = " << wd::number << endl;//作用域限定符

wd::print();

return 0;

}

#include

#include

using std::cout;

using std::endl;

int number = 1;

namespace wd

{

int number = 10;

void print(int number)

{

cout << "形参number = " << number << endl;

cout << "命名空间中number = " << wd::number << endl;

cout << "全局number = " << ::number << endl;//匿名命名空间

printf("helloworld\n"); //没有重名,可以直接写,不需要加匿名空间作用域限定符

::printf("helloworld\n");

}

//命名空间是可以嵌套的

namespace wh

{

int number = 200;

}

}//end of namespace

int main(int argc, char **argv)

{

wd::print(20);

cout << "wh::number = " << wd::wh::number << endl;

return 0;

}

相关推荐

苹果手机有什么抢红包软件
365信息网

苹果手机有什么抢红包软件

📅 09-11 👁️ 8948
38年前罗布泊双鱼玉佩事件,真相究竟是什么?
英超365bet体育投注

38年前罗布泊双鱼玉佩事件,真相究竟是什么?

📅 10-19 👁️ 8560
如何买到全新的手机号
365信息网

如何买到全新的手机号

📅 06-28 👁️ 1321
Dnf远古摸金打哪个
365信息网

Dnf远古摸金打哪个

📅 08-31 👁️ 2773
怎样在word文档中打印a3格式(word文档怎么打印格子)
三星Galaxy Note系列
365bet世界杯欢迎您

三星Galaxy Note系列

📅 07-08 👁️ 8215
《Fate/Grand Order》命运-冠位指定之英灵培养攻略
365bet世界杯欢迎您

《Fate/Grand Order》命运-冠位指定之英灵培养攻略

📅 10-25 👁️ 5816
「仆人」 - 原神WIKI
365信息网

「仆人」 - 原神WIKI

📅 09-12 👁️ 6943
SAP安全库存(时间)详解
365信息网

SAP安全库存(时间)详解

📅 09-12 👁️ 3044