一,C++关键字(C++98)
C++总计63个关键字,C语言32个关键字。
ps:下面我们只是看一下C++有多少关键字,不对关键字进行具体的讲解。在以后的学习中会会了解的更深。
二,命名空间
2.1 命名冲突
在C语言的语法中,有时候会遇到这样的情况:
#include <stdio.h> #include <stdlib.h> int rand = 0; int main() { printf("%d\n", rand); return 0; }
我们的本意是创建一个全局的 rand 变量,再进行输出。那为什么会报错呢?
原因:这是因为 rand 是一个库函数,当我们包含头文件 <stdlib.h> 时,在预处理阶段会展开头文件,里面的 rand 函数与我们定义的 rand 变量发生了冲突。编译器会自动识别 rand 是一个库函数,而不是对整形打印。
2.2 关键字namespace
使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染 。
首先我们知道在全局域(全局变量)和局部域(局部变量),可以分别定义名字相同的变量,但是使用时是局部优先。
那如何访问全局变量呢?就要用到域作用限定符::
当域作用限定符前没有其他符号时,就默认访问全局变量。
命名空间的本质也是一个域,叫做命名空间域。
它与全局域和局部域的区别是:命名空间域不影响生命周期。
使用方法是:后面跟命名空间的名字,然后接一对{}即可,里面的内容为命名空间的成员。
使用变量,函数时,编译器的默认查找规则是:先在当前局部域查找,再在全局域中查找,但是不会在命名空间域里查找。
当要指定打印命名空间域中的变量时,在域作用限定符前要加上域的名字。
2.2.1 命名空间中可以定义变量/函数/类型
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
在 test.cpp 中:
namespace bit { int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; }
2.2.2 命名空间可以嵌套
在大型项目中一般最多嵌套两三层,平时不会嵌套。
在 test.cpp 中:
namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } }
2.2.3 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
比如在 test .h 中:
namespace N1 { int Mul(int left, int right) { return left * right; } }
一个工程中的 test.h 和上面 test.cpp 中两个N1会被合并成一个。
但是合并后不能有同名的变量,函数等,否则也会报错。要用嵌套解决。
2.3 命名空间的使用
2.3.1 指定访问域中成员:加命名空间名称及作用域限定符
2.3.2 使用using将命名空间中某个成员引入
可以指定域中的某个成员进行展开,使用它时可以不加作用域限定符。但是使用其他成员时要加。
比如 b 经常使用,a 偶尔使用时:
2.3.3 使用using namespace 命名空间名称 引入
当我们要多次使用域中某个成员时,每次都要 域名+限定符 十分麻烦。就可以使用 using namespace + 名称 将域进行展开。
2.4 当两个命名空间定义相同成员,同时展开时会报错。
所以命名空间不能随便展开!
namespace bit { int a = 0; int b = 1; int c = 2; } namespace hello { int a = 0; int b = 1; int c = 2; } //展开命名空间 using namespace bit; using namespace hello; int main() { printf("%d\n", a); printf("%d\n", a); printf("%d\n", a); printf("%d\n", a); printf("%d\n", a); printf("%d\n", a); return 0; }
2.5 总结
所以说,使用 using namespace 展开命名空间的本质可以理解为改变了编译器默认的查找规则,不仅会先在局部域,全局域中查找,最后还会到命名空间域中查找。
但是要注意的是命名空间域的展开不是像头文件在预处理时展开的那样直接拷贝进来,而是相当于增加了一个声明。
三,输入&输出
3.1 C++也有一套新的输入输出流。
cout 和 cin 包含在头文件< iostream >中,在使用时为啥要展开命名空间 std 呢?
原因:是为了防止标准库中定义的内容和你定义的内容发生冲突。std 是官方库的命名空间,把标准库里的内容保护起来。
说明:
- 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
- cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
- <<是流插入运算符,>>是流提取运算符。
- 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。
注意:
关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度,控制整形输出进制格式等等。因为C++兼容C语言的用法,这些又用得不是很多,所以在涉及这方面时建议使用printf 来控制格式,这样更方便。
3.2 std命名空间的使用惯例
std是C++标准库的命名空间,如何展开std使用更合理呢?
- 在日常练习中,建议直接using namespace std即可,这样就很方便。
- using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
四,缺省参数
4.1 缺省参数概念
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
举例:
4.2 缺省参数的分类
4.2.1 全缺省参数
函数的所有参数均由自己指定。
4.2.2 半缺省参数
函数的参数部分传实参,其余的自己指定。
半缺省参数必须从右往左缺省,如图 b ,c 是缺省的,实参50床给 a。
注意:
- 半缺省参数必须从右往左依次来给出,不能间隔着给。
- 缺省参数不能在函数声明和定义中同时出现,若有声明和定义分离的情况,只能在声明中缺省。
举例:
- 间隔缺省会报错
#include <iostream> using namespace std; void Func(int a , int b = 20, int c ) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl << endl; } int main() { Func(50, ,30); return 0; }