本篇内容介绍了“C++核心技术知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
1. 命名空间namespace
使用过C++的朋友一定听说过命名空间吧。是的,就是你经常看到的namespace, 虽然大多数同学都会用namespace, 但是只有少部分非常清楚namespace的作用。
下面,我就来简单总结一下吧。命名空间是1995年引入标准C++(ANSIC++)中的, 那么为什么要引入这么一个概念呢?
先讲个故事: 同一个班级中有两个相同名字的同学,比如都叫A, 那么如果老师喊A的时候,就会导致冲突,不知道是哪个A应该答应。这个时候老师为了把这两个同学区分开,就会重新给他们取个名字,分别叫BA和CA, 来避免名字冲突的问题,其实在C++也是如此。
命名空间最重要的作用就是避免程序中的命名冲突问题。
我们在给代码中的类或对象取名字时,很可能会遇到同名的情况,有的朋友可能觉得自己的代码自己很熟悉,怎么可能同名?
是的,如果这个工程的作者只有你自己的话,同名的可能性确实比较小,但是在工作中我们接触到的项目往往非常庞大,项目组成员可能涉及十几人,几十人甚至上百人不等(某些开源项目,作者可能上千人),在这种情况下很难保证代码中命名不冲突。
还有一种命名冲突的情况是两个独立的模块,但是有相同功能的函数,或变量,当我们的项目同时引用这两个模块同名对象时,编译器便不知道该用哪一个模块里面的对象了。
因此,引入命名空间的概念是非常合理且必要的事情。
形象点儿讲,namespace就像工程中的栅栏,把相关的代码(类,对象,函数,变量...)圈起来,这些namesapce 圈圈就相互独立,互不影响,各玩各的。画风就像下面:
说了这么多,那么namespace该怎么用呢?请看下面:
#include<iostream>using namespace std;int main(){ cout << "Hello World!" << endl;}
这里,我们还是以通俗易懂、简单友好的的Hello World为例。std就是C++标准命名空间。如果你不想带上它,那么cout标准输出就用不了,因为他们被锁进了std这个圈里了,在其他地方是没有办法访问的。
如果非要用,那么代码的画风就变成下面这样的了,使用一个范围操作符 "::", 表示要使用std中的cout进行输出
#include<iostream>int main(){ std::cout << "Hello World!" << std::endl;}
看到了吗,cout要想出std这个圈,就必须带上std这个钥匙,对于其他模块同样的道理。在日常项目中,我们还常常会用到boost库,那么代码中就需要boost这把钥匙:
using namespace boost;
或者
boost::xx
命名空间相当于圈定一个作用域,如果希望在某个作用域中使用另一个作用域的对象,便要使用using导入该对象所在命名空间,或者在这个对象前面加上该命名空间的名称。
这样看来似乎非常简单,确实,简单在代码中加上命名空间就好了,如果真是如此,我也没有比较写这个话题了,但是细看的话,还是能发现一些坑和一些小技巧的。
(1)using虽好,不要用在头文件中
最近在看同事写的代码时发现有几处在头文件中使用using的情况,虽然在代码前面简单粗暴地用using一下子导入整个命名空间,快速解决问题。
但是,我们在开发的时候一个头文件可能被很多个模块引用(我们的头文件供其他的人使用,我们很难确定别人会用在哪些地方),如果头文件中直接用using,很容易引起命名冲突的问题,所以为了降低debug的痛苦,建议不要在头文件中使用using!
(2)避免大范围使用using
这个还是为了降低命名冲突的风险。
如果我们只是想用某个命名空间的某个对象时,在用using引入命名空间时,最好具体到这个对象所在的最小范围命名空间。比如我要使用string,cin, cout,就可以这样写:
using std::string;using std::cin;using std::cout;
这里string就是std的子命名空间,大大缩小了命名空间范围。
当然,大多数情况下我们会在代码中直接使用这样的形式(命名空间名加上范围操作符加上):
void func(){ std::cin ...; std::string...; std::cout...;}
上面说了那么多都是在讲怎么导入别人的命名空间,下面说一下怎么定义我们自己的命名空间。
其实也很简单,就是去掉using,如下:
namespace 命名空间名{ 表达式1; ... ... 表达式2;}
当然,我们也可以对命名空间进行嵌套操作:
namespace 命名空间名1{ ... namespace 命名空间名2{ ... }}
那么,命名空间名是唯一的吗?或者说必须要有命名空间名,答案是:否
namespace 命名空间名3 = 命名空间名1; //命名空间1等价于命名空间3//匿名命名空间namespace{ ......}
上面命名空间3等价于命名空间1相当于给命名空间1取了一个别名,因为有的时候我们会遇到比较冗长的命名空间名,为了避免 繁琐,可以用一个简短的名字替代。
除此之外,上面还有个匿名命名空间的例子,那么这个有什么用呢?
像上面,匿名命名空间形如:
namespace{ const int k = 10;}
虽然名为匿名,但是编译器在编译这部分代码时,会为它生成一个唯一的名字,而且还附加一条using指令,效果如下面的代码所示:
namespace __UNIQUE_NAME_{ const int k = 10;}using namespace __UNIQUE_NAME_;
虽然编译器能给匿名命名空间生成一个特殊的名字,但是这个命名空间对全局是不可见的,只在当前文件中有用,而有名字的命名空间对全局是可见的,全局有效。
这个特点有点像static关键字,被static加持的全局变量,也只能在当前文件中有效。实际上匿名命名空间就是C++用来替代static的,C++新标准推荐使用匿名空间而不推荐static。
“C++核心技术知识点有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。