wordpress教程视频教程关键词优化精灵
本章详细解说:namespace 。
namespace:
namespace,意为:命名空间,c++的关键字(关键字,就是提示:取变量名,函数名时不能与之撞名)。
namespace的价值:
为了解决命名冲突。
何为命名冲突?在一个作用域中,变量int 叫 a, 一个函数的名字也叫a。
事实胜于雄辩:
这是一段散发着浓浓C味儿的代码,但是在cpp下同样可以编译。
何故?c++兼容C
#include <stdio.h>
#include <stdlib.h>int rand = 10;
int main()
{return 0;
}
重点是:
我们在main函数外声明一个变量rand,(这种声明在函数外的变量,称为全局变量,全局变量在程序的执行期间都是可以访问的)。而巧合的是,stdlib.h里声明一个函数叫rand(),恰好与rand同名。
这就发生了命名冲突,namespace就是为此类情况而生。
namespace的定义:
既然namespace创造出来就是为了避免命名冲突,那具体怎么个避免法呢?
- namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
//各种声明namespace BOB//因为老夫名叫BearOnBasket,便缩写为BOB;各位取名尽可随意
{// 变量int rand = 10;// 函数int Add(int a, int b){return a + b;}//类型struct node{int val;struct node* next;};
}//与typedef不同,这里不能写分号//各种函数...
- namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量。
相当于不同区域里有很多的重名的人,不同区域里可以同时出现许多张三,你要找的:究竟是A市的张三,还是D市的张三...
现在一个rand在BOB这个域里,一个rand()在全局域里,俩rand的存在因不在一个域里而合理化,但要准确地访问到目标rand,又该如何做呢?
::域作用限定符——主打一个访问准确
namespace BOB
{//命名空间中可以定义变量/类型/函数int rand = 10;
}
int main()
{printf("%p\n",rand);//访问stdlib.h里的函数指针printf("%d\n", BOB::rand);// 命名空间名字 :: 变量名 ——保证你访问到目标区域下的目标变量return 0;
}
运行截图:
再看一段代码:
int a = 1;
int main()
{int a = 100;printf("a = %d\n",a);//猜猜两个a分别是多少printf("a = %d\n",::a);return 0;
}
答案:
a = 100 : 当函数局部域与全局域都有撞名的变量,采用就近原则:离调用变量函数(这里指printf())近的变量优先
a = 1 : 当 :: 前没有命名空间名,默认访问全局域的变量。
再看创建一个命名空间里的类型变量:
namespace BOB
{//命名空间中可以定义变量/类型/函数int rand = 10;struct node{int val;struct node* next;};int Add(int a, int b){return a + b;}
}int main(){//创建一个node类型的结构struct BOB::node newNode;//划重点,struct算关键字,::后接变量名。故是struct BOB::newNode.val = 10;//完成初始化newNode.next = NULL;printf("%d\n",newNode.val);return 0;}
- namespace只能定义在全局,当然它还可以嵌套定义。
在说明namespace定义时,如果有小伙伴细心的话,会发现:
namespace不在任何函数里,同全局变量一样,定义在函数之外。
嵌套定义——域中域
就像这样:
namespace Bear
{namespace Panda{int a = 12;//定义变量int Add(int x,int y)//函数的定义{return x + y;}}namespace IceBear{int a = 20;int Add(int x, int y){return (x + y )* 10;}}
}
又到了访问环节,既然命名空间定义嵌套,访问自然也要嵌套:
namespace Bear
{namespace Panda{int a = 12;//定义变量int Add(int x,int y)//函数的定义{return x + y;}}namespace IceBear{int a = 20;int Add(int x, int y){return (x + y )* 10;}}
}
int main()
{printf("%d\n",Bear::Panda::a);printf("%d\n",Bear::IceBear::a);printf("%d\n",Bear::Panda::Add(1,2));//不出所料结果应该是3printf("%d\n",Bear::IceBear::Add(1,2));//结果为30return 0;
}
确实不出所料。
- 项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
这句,只做理解:
在以后写代码,要想把多个文件合成为一且不影响运行,我们可以使用namespace,同一个命名空间,编译器在编译时逻辑上是合成为一的。
- C++标准库都放在⼀个叫std(standard)的命名空间中。
怎么说?C++的标准库指的就是一些写好的文件包含:类、函数以及类型,它们的外层用一个叫做std的namespace包含。那么,同理,要想访问库里的类,就要使用 std ::
namespace的使用:
namespace BOB
{int a = 1;int b = 0;
}int main()
{printf("%d\n",a);return 0;
}
所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:
- 指定命名空间访问,项⽬中推荐这种⽅式。
也就是我们前面所说的 ::
- using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。
确实,经常访问的成员而且不存在冲突,我们总是 ”命名空间名::“ 显得不是很方便。
namespace BOB
{int a = 1;int b = 0;
}
using BOB::a;//划重点
int main()
{printf("%d\n",a);return 0;
}
如此,就可以成功访问BOB里的a了。
- 展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤
一旦展开整个命名空间,就相当于全部成员暴露在外;这时候,一旦发生命名冲突就无法隔开。日常写小程序倒鲜少发生,反而方便。但是项目不推荐使用。
namespace BOB
{int a = 1;int b = 0;
}
using namespace BOB;//展开整个命名空间
int main()
{printf("%d\n", a);printf("%d\n", b);return 0;
}