什么是C++
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持 面向对象 的程序设计语言应运而生。 1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的 程序设计,还可以进行面向对象的程序设计。
C++的发展史
1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C
语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with
classes。
语言的发展就像是练功打怪升级一样,也是逐步递进,由浅入深的过程。我们先来看下C++的历史版本。
C++还在不断的向后发展。但是:现在公司主流使用还是C++98和C++11,所有大家不用追求最新,重点将C++98和C++11掌握好,等工作后,随着对C++理解不断加深,有时间可以去琢磨下更新的特性。
C++关键字(C++98)
C++总计63个关键字,C语言32个关键字
ps:下面我们只是看一下C++有多少关键字,不对关键字进行具体的讲解。后面我们学到以后再
细讲。
C语言的关键字:
命名空间
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,
以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的
举例:
#include<stdio.h> #include<stdlib.h> //命名冲突 int rand = 10; // C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决 int main() { printf("%d\n",rand); // 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数” return 0; }
执行:
解释:
在C语言中,rand是一个库函数,用于生成伪随机数。然而,在该代码中,rand被重新定义为一个整数变量并赋值为10。这导致命名冲突。
要解决这个问题,你可以考虑以下两种方法之一:
改变变量名:将变量名rand更改为其他名称,以避免与库函数rand发生冲突。 使用C++:将代码保存为以.cpp为扩展名的文件,并使用命名空间来解决命名冲突。
命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
1. 正常的命名空间定义
1.1命名空间中可以定义变量/函数/类型(结构体)
// 1. 正常的命名空间定义 namespace bit { // 命名空间中可以定义变量/函数/类型 int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; }
1.2命名空间可以嵌套
namespace zzc { //命令空间中可以定义变量/函数/类型 int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; namespace zzc1 { int rand = 1; } } int Add(int left, int right) { return (left + right) * 10; } int main() { printf("%d\n",zzc::rand); printf("%d\n", zzc::zzc1::rand);//命名空间的嵌套 printf("%d\n",Add(1,2)); printf("%d\n",zzc::Add(1,2)); struct zzc::Node node;//命名空间里面的结构体类型创建变量 return 0; }
代码执行:
1.3同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
注意:一个命名空间就定义了一个新的作用域 ,命名空间中的所有内容都局限于该命名空间中
#include<stdio.h> #include<iostream> #include<stdlib.h> //Stack.h namespace zzc { void StackInit() { cout << "void StackInit()" << endl; } namespace zzc1 { int rand = 0; } } //Queue.h namespace zzc { void QueueInit() { cout << "void QueueInit()" << endl; } namespace zzc { int rand = 1; } } using std::cout; using std::endl; #include"Stack.h" #include"Queue.h" int main() { //命名空间的合并 zzc::StackInit(); zzc::QueueInit(); return 0; }
执行:
命名空间使用
命名空间中成员该如何使用呢?比如:
namespace bit { // 命名空间中可以定义变量/函数/类型 int a = 0; int b = 1; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; } int main() { // 编译报错:error C2065: “a”: 未声明的标识符 printf("%d\n", a); return 0; }
执行:
命名空间的使用有三种方式:
1.加命名空间名称及作用域限定符
在C++中,::被称为作用域限定符(Scope Qualifier)。作用域限定符用于指定特定的作用域,并在该作用域中查找标识符。
通过使用作用域限定符,你可以在命名空间、类、结构体、枚举等作用域中精确地引用特定的成员或标识符。
作用域限定符的语法是namespace(命名空间zzc)::identifier或 class(类名)::identifier,其中namespace是命名空间的名称(zzc),class是类的名称,identifier是成员或标识符的名称。
namespace zzc { //命令空间中可以定义变量/函数/类型 int rand = 10; }
执行:
2.使用using将命名空间中某个成员引入
部分展开(授权) -- 比如下面允许(授权)使用者去zzc里面的Add去访问和引用。
图解:
代码实现:
namespace zzc { //命令空间中可以定义变量/函数/类型 int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; //嵌套 namespace zzc1 { int rand = 1; } } //部分展开(授权) using zzc::Add; int main() { printf("%d\n",zzc::Add(1,2)); printf("%d\n",Add(1,2)); }
3.使用using namespace 命名空间名称引入
全部展开(授权)--展开命名空间,意思是把所有墙都给它拆掉,把命名空间里面所有内容展开,默认是找全局的,那就没有区别之分了,所以很容易引起命名冲突,是一件很危险的事情
在使用using namespace时,存在一些潜在的风险和注意事项,因此需要谨慎使用。以下是一些相关的考虑因素: 命名冲突:如果你使用using namespace引入了多个命名空间,而这些命名空间中有相同名称的成员,就会导致命名冲突。这可能会使代码难以理解,且不明确引用的成员可能会导致错误的调用。 命名空间污染:使用using namespace会将整个命名空间的所有成员引入当前作用域,这可能导致命名空间的成员与当前作用域中的其他标识符发生冲突。这可能会引入不必要的歧义和错误。 可读性和维护性:在代码中广泛使用using namespace可能会降低代码的可读性和维护性。其他开发人员可能不熟悉引入的命名空间,并且很难追踪代码中使用的具体成员的来源。
在展开namespace之前运行:
由于rand函数是头文件stdlib.h里面的内容,所以不初始化的时候是随机值。(rand函数的函数名就是函数的地址)
在展开zzc这个namespace之后:
#include<stdlib.h> using namespace zzc;
可以发现,rand的打印不明确,这是为什么呢?原因是,命名空间zzc相当于用一道墙把命名空间域里面的内容和全局变量隔离起来了,现在使用using namespace关键字,相当于把墙拆了,就引起了名字冲突 -- zzc里面rand函数与头文件里面的rand函数的冲突。
总结:还是指定最安全,不要把"墙"拆掉(但是指定需要大量用到,如果觉得命名空间zzc::使用次数过多,那么请使用上面第2点的部分展开)
【C++初阶】第一站:C++入门基础(上) -- 良心详解-2