• 『C++成长记』C++入门——命名空间&缺省参数


     🔥博客主页:小王又困了

    📚系列专栏:C++

    🌟人之为学,不日近则日退

    ❤️感谢大家点赞👍收藏⭐评论✍️


    目录

    一、C++的认识

    📒1.1什么是C++

    📒1.2C++的发展

    二、C++关键字

    三、命名空间

    📒3.1为什么有命名空间

    📒3.2命名空间定义

    📒3.3命名空间使用

    📒3.4命名空间的嵌套

    📒3.5std命名空间的使用

    四、C++的输入和输出

    五、缺省参数

    📒5.1缺省参数的定义

    📒5.2 缺省参数分类

    📒5.3缺省参数出现的位置


    🗒️前言:

    C++是在C语言的基础上发展而来的,C++优化了C语言的很多问题,让使用者使用起来更加方便,从今天开始我们将进入C++的学习,学习C++的奇妙之处。

    一、C++的认识

    📒1.1什么是C++

            C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的 程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机 界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。 1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一 种新的程序语言。命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。

    📒1.2C++的发展

           1979年,贝尔实验室的本贾尼等人试图分析 unix 内核的时候,试图将内核模块化,于是在C 语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with classes。

    C++的历史版本:

    二、C++关键字

     C++一共有63个关键字,其中有32个是C语言中的关键字

    三、命名空间

    📒3.1为什么有命名空间

         在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化, 以避免命名冲突或名字污染。

    例如:

    1. #include
    2. #include
    3. int rand = 10;
    4. int main()
    5. {
    6. printf("%d", rand);
    7. return 0;
    8. }


     在这段程序中,不引用头文件#include 是可以正常运行的,但引用后程序就会报错,这是什么原因呢?因为 rand 中已有了定义,这里报了重定义的错误。

         命名空间分割了全局命名空间,其中每一个命名空间是一个作用域。域是一种空间概念,常见的域有:局部域、全局域、类域、命名空间域,域会影响访问和生命周期。

    📒3.2命名空间定义

         命名空间的定义由两部分构成:首先是关键字namespace,后面跟命名空间的名字,然后接一对花括号,花括号中即为命名空间的成员。 命名空间中可以定义变量、函数、类型和其他命名空间。

    1. namespace N1//命名空间的名字
    2. {
    3. //定义变量
    4. int rand = 10;
    5. //定义函数
    6. int Add(int left, int right)
    7. {
    8. return left + right;
    9. }
    10. //定义类型
    11. struct Node
    12. {
    13. struct Node* next;
    14. int val;
    15. };
    16. //嵌套命名空间
    17. namespace N2
    18. {
    19. int Sub(int left, int right)
    20. {
    21. return left - right;
    22. }
    23. }
    24. }

    注意:

    • 一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
    • 用一个工程中允许出现多个相同名称的命名空间,编译器最后会将它们合并为一个命名空间。 

    📒3.3命名空间使用

    命名空间的使用有三种方式:

    • 加命名空间名称及域作用限定符
      1. namespace N
      2. {
      3. int a=10;
      4. int b=5;
      5. }
      6. int main()
      7. {
      8. printf("%d\n", N::a);
      9. return 0;
      10. }
    •  使用 using 将命名空间中某个成员引入
      1. using N::b;
      2. int main()
      3. {
      4. printf("%d\n", N::a);
      5. printf("%d\n", b);
      6. return 0;
      7. }
    •  使用 using namespace 命名空间名称引入(展开命名空间)
      1. namespace N
      2. {
      3. int a=10;
      4. int b=5;
      5. }
      6. int a=20;
      7. using namespce N;
      8. int main()
      9. {
      10. printf("%d\n", a); //a不明确,有二义性
      11. printf("%d\n", ::a); //访问全局的a
      12. printf("%d\n", N::a); //访问N中的a
      13. printf("%d\n", b);
      14. return 0;
      15. }

      N中的成员a 就与全局作用域中的a 产生了冲突。这种冲突是允许存在的,但是要想使用冲突的名字,我们就必须明确指出名字的版本。main函数中所有未加限定的a都会产生二义性错误。

    这时我们必须使用域作用限定符(::)来明确指出所需的版本

    • : :a来表示全局作用域中的a
    • N: :a来表示定义在N中的a

     注意:

    如果命名空间没有展开,编译器默认是不会搜索命名空间中的变量,去访问变量是访问不到的。

    访问的优先级:局部域 > 全局域

    📒3.4命名空间的嵌套

          嵌套的命名空间同时是一个嵌套的作用域,它嵌套在外层命名空间的作用域中。嵌套的命名空间中的名字遵循的规则与往常类似:内层命名空间声明的名字将隐藏外层命名空间声明的同名成员。在嵌套的命名空间中定义的名字只在内层命名空间中有效,外层命名空间的代码想要访问它必须在名字前添加限定符。

    1. namespace N
    2. {
    3. int a = 10;
    4. namespace N1
    5. {
    6. int a = 20; //将外层作用域的a隐藏了
    7. int b = 15;
    8. namespace N2
    9. {
    10. int c = N1::b;
    11. }
    12. }
    13. int main()
    14. {
    15. printf("%d\n", N::N2::c);
    16. printf("%d\n", N::N1::a);
    17. printf("%d\n", N::a);
    18. return 0;
    19. }

    📒3.5std命名空间的使用

    std是C++标准库的命名空间,如何展开std使用更合理呢?

    1. 在日常练习中,建议直接using namespace std;即可,这样就很方便。
    2.  using namespace std;展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型、对象、函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模 大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间例如: using std::cout展开常用的库对象、类型等方式。 

    四、C++的输入和输出

    1. #include
    2. using namespace std;
    3. int main()
    4. {
    5. int a = 10;
    6. double b = 10.5;
    7. cout << a << endl;
    8. cout << b << endl;
    9. return 0;
    10. }

    我们在项目中要经常使用 coutendl,每次指定命名空间很不方便,直接展开会全部暴露,有冲突风险,我们可以指定展开来解决问题。

    1. using std::cout;
    2. using std::endl;

    说明:

    • 使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
    • coutcin 是全局的流对象,endl 是特殊的C++符号,表示换行输出,他们都包含在包含 < iostream >头文件中。
    • <<是流插入运算符,>>是流提取运算符。
    • 使用C++输入输出更方便,不需要像 printf和scanf 输入输出时那样,需要手动控制格式。 C++的输入输出可以自动识别变量类型

    五、缺省参数

    📒5.1缺省参数的定义

         缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

    1. void Func(int a = 5)
    2. {
    3. cout << a << endl;
    4. }
    5. int main()
    6. {
    7. Func(); // 没有传参时,使用参数的默认值
    8. Func(10); // 传参时,使用指定的实参
    9. return 0;
    10. }

    上面代码在第一次调用 Func() 时,没有传递参数,a 就使用了缺省值。

    📒5.2 缺省参数分类

    • 全缺省参数 -- 所有参数都给了缺省值
    1. void Func(int a = 10, int b = 20, int c = 30)
    2. {
    3. cout<<"a = "<
    4. cout<<"b = "<
    5. cout<<"c = "<
    6. }
    7. int main()
    8. {
    9. Func(123);
    10. Func(12);
    11. Func(1);
    12. Func();
    13. return 0;
    14. }

        全缺省参数在传参时,参数是按照从左往右的顺序进行缺省的,不能跳着缺省,例如:Func(1,  ,3) ,让第一个形参和第三个形参都使用传递值,而让第二个参数使用缺省值,这种做法是不被允许的。

    • 半缺省参数 -- 部分的参数给了缺省值
    1. void Func(int a, int b = 20, int c = 30)
    2. {
    3. cout<<"a = "<
    4. cout<<"b = "<
    5. cout<<"c = "<
    6. }
    7. int main()
    8. {
    9. Func(123);
    10. Func(12);
    11. Func(1);
    12. return 0;
    13. }

         半缺省参数必须从右往左依次来给出,不能间隔着给。

    注意:

    1. 缺省参数不能在函数声明和定义中同时出现,只能出现在函数声明中。
    2. 缺省值必须是常量或者全局变量。

    📒5.3缺省参数出现的位置

          缺省参数只能出现在函数声明中,如下面的代码,在声明和定义中都给了缺省参数,而且给定的值不相同,就不知道以哪个值为准。

    1. //a.h
    2. void Func(int a = 10);
    3. //a.cpp
    4. void Func(int a = 20)
    5. {}

          不能只在声明处给缺省参数,如下面的代码,如果只在声明处给缺省参数,在其他的文件中没有缺省参数,就不知是什么值。

    1. //a.cpp
    2. void Func(int a = 10)
    3. {}
    4. //b.cpp
    5. void Func(int a)
    6. {}

     本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

  • 相关阅读:
    vuex和pinia
    15.3K Star,超好用的开源协作式数字白板:tldraw
    Linux 文件读写
    科研笔记:可用数据集整理(ing)
    UE4_材质_雨滴涟漪效果ripple effect_ben教程
    正点原子MP157系统移植和根文件系统构建视频教程之uboot命令学习笔记
    数组(1)
    岩藻多糖-聚乙二醇-转铁蛋白,Transferrin-PEG-Fucoidan,转铁蛋白-PEG-岩藻多糖
    如何理解UML2.5.1(01篇)
    Linux安装MySQL8.0服务
  • 原文地址:https://blog.csdn.net/2301_76207836/article/details/132989229