千家信息网

C++核心技术知识点有哪些

发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,本篇内容介绍了"C++核心技术知识点有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 命名空
千家信息网最后更新 2024年11月18日C++核心技术知识点有哪些

本篇内容介绍了"C++核心技术知识点有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1. 命名空间namespace

使用过C++的朋友一定听说过命名空间吧。是的,就是你经常看到的namespace, 虽然大多数同学都会用namespace, 但是只有少部分非常清楚namespace的作用。

下面,我就来简单总结一下吧。命名空间是1995年引入标准C++(ANSIC++)中的, 那么为什么要引入这么一个概念呢?

先讲个故事: 同一个班级中有两个相同名字的同学,比如都叫A, 那么如果老师喊A的时候,就会导致冲突,不知道是哪个A应该答应。这个时候老师为了把这两个同学区分开,就会重新给他们取个名字,分别叫BA和CA, 来避免名字冲突的问题,其实在C++也是如此。

命名空间最重要的作用就是避免程序中的命名冲突问题。

我们在给代码中的类或对象取名字时,很可能会遇到同名的情况,有的朋友可能觉得自己的代码自己很熟悉,怎么可能同名?

是的,如果这个工程的作者只有你自己的话,同名的可能性确实比较小,但是在工作中我们接触到的项目往往非常庞大,项目组成员可能涉及十几人,几十人甚至上百人不等(某些开源项目,作者可能上千人),在这种情况下很难保证代码中命名不冲突。

还有一种命名冲突的情况是两个独立的模块,但是有相同功能的函数,或变量,当我们的项目同时引用这两个模块同名对象时,编译器便不知道该用哪一个模块里面的对象了。

因此,引入命名空间的概念是非常合理且必要的事情。

形象点儿讲,namespace就像工程中的栅栏,把相关的代码(类,对象,函数,变量...)圈起来,这些namesapce 圈圈就相互独立,互不影响,各玩各的。画风就像下面:

说了这么多,那么namespace该怎么用呢?请看下面:

#includeusing namespace std;int main(){    cout << "Hello World!" << endl;}

这里,我们还是以通俗易懂、简单友好的的Hello World为例。std就是C++标准命名空间。如果你不想带上它,那么cout标准输出就用不了,因为他们被锁进了std这个圈里了,在其他地方是没有办法访问的。

如果非要用,那么代码的画风就变成下面这样的了,使用一个范围操作符 "::", 表示要使用std中的cout进行输出

#includeint 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++核心技术知识点有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0