C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

07-16 543阅读

一、前言

        我们都知道,C++是C语言的前身,C++里面的很多语法,都来自于C语言,C++的语法是完全兼容于C语言的。可是,又有一个疑问?有什么问题是非C++不可的呢?

        下面,我们将以不破不立的原则,进而铺垫C++的基础知识,并展开讲解。

二、命名空间

1.问题导向
#include
#include
int rand = 1314;
int main()
{
	printf("%d\n", rand);
	return 0;
}
/*
 *这组代码中,就存在了一个不可避免的 会存在编译错误:
 *error C2365: “rand”: 重定义;以前的定义是“函数”
 *warning C4477: “printf”: 格式字符串“%d”需要类型“int”的参数,但可变参数 1 
 *拥有了类型“int (__cdecl *)(void)”  
 */

        不难理解,rand是生成随机数的函数名,其函数的声明存放于头文件中,而我们又定义了一个全局变量rand;这就导致了上面的错误,我们称为命名冲突;

  • 问:自己写代码的时候,命名稍加注意一下,不就可以了吗?
  • 回:虽然你自己写代码的时候,不会发生命名冲突的问题,但你不能保证,多人协作写一个项目的时候,不会出现命名冲突的问题,毕竟每个人的想法都是参差不齐的。

            为了解决命名冲突的问题,C++引入了一个新的关键字——namespace,namespace后跟一对{},中间用于变量的定义,函数的声明与定义,类的声明与定义等等;可以为我们在全局域生成一个命名空间域;主要用于解决命名冲突、组织代码、提高代码的可读性和可维护性。

            下面的代码,是在域中定义一个malloc为函数名的交换函数,和以rand为变量名的变量。包含头文件后,编译器不会报上面的错误。

    C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

    2.namespace的定义
    • namespace的本质,在用途方面,可以类似于电脑分盘(新建文件夹),在不同的盘符(文件夹)中可以定义相同的文件标识;
    • 不同的域可以使用相同的标识符,如局部域和作用域,都可以定义变量a;
    • 在同一域中,不能出现两个或两个以上的相同的标识符
    • 多文件中,存在相同的命名空间域名的时候,编译的时候,会形成同一个域;
    • namespace可嵌套使用;
    • namespace只可在全局域中使用;
    • C++的作用域主要有四种,函数局部域、全局域、命名空间域、类域。函数局部域、全局域会改变变量或函数的作用域和生命周期,而命名空间域、类域只改变其作用域,不改变其生命周期;
    • C++的标准域,定义在 std 域中;
    • 编译器找变量、函数、或类的出处,默认是局部域和全局域(先局部域,后全局域);若找不到,则编译器报错;——由此更能体现命名空间对命名冲突问题的解决;
    • 下面将对上面所说的某些现象,进行验证与反馈~,若无问题可直接跳转命名空间的使用

      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

      //.h文件
      #include
      namespace zmh
      {
      	void Print();
      }
      //.cpp文件
      #include"zmh.h"
      namespace zmh
      {
      	void Print()
      	{
      		printf("残风也想永存:第一个C++代码\n");
      	}
      }
      //.main文件
      #include"zmh.h"
      using namespace zmh; // 这里是对命名空间的一种使用方法
      int main()
      {
          //验证:多文件中,存在相同的命名空间域名的时候,编译的时候,会形成同一个域;
          //若成功调用Print(),则验证成功!!!
      	Print();
      	return 0;
      }
      
      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)
      3.命名空间的使用

              我们已经知道,编译器找变量、函数、或类的出处,默认是局部域和全局域(先局部域,后全局域);那我们就想,怎么才能告诉编译器,去全局域,去找出处呢?

              答案是有的,这里将学习一个新的操作符 ‘::’——作用域解析操作符,而是用于指定某个标识符的所属作用域或命名空间的特殊符号。

              ‘::’,操作符前是全局域(双冒号前面什么都没有,则代表全局域)或者是命名空间的域名,后面则是我们要访问的变量,函数或类。

               命名空间使用总结:

              注: ‘::’不仅仅可以访问全局域和命名空间域,但目前们只需要掌握这两个用途即可  

      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

              如果我们对命名空间域中某一个变量或函数的使用率更频繁的时候,每次都要通过上面的访问方式,是不是有点太过繁琐了?难到就没有其它的解决方法了吗?

              是有的,C++为我们提供了一个using关键字,在全局域中使用using关键字,可以解决上面的问题。

      其使用方法由以下两种:

      using (命名空间域名)::(要访问的变量、函数或类);   

      // 对某个要频繁使用的变量、函数或类进行展开
      using namespace (命名空间域名); 

      // 对整个命名空间域进行展开

      功效,可以让我们在使用某个变量、函数或类的时候,不再需要 (命名空间域名)::(要访问的变量、函数或类) ,而是直接(要访问的变量、函数或类)即可。

      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

      C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

      命名空间使用总结:

      命名空间使用方法一:

      (命名空间域名)::(要访问的变量、函数或类)

      命名空间使用方法二:

      using (命名空间域名)::(要访问的变量、函数或类);   

      // 对某个要频繁使用的变量、函数或类进行展开

      命名空间使用方法三:
      using namespace (命名空间域名); 

      // 对整个命名空间域进行展开

       三、C++的输入&输出流

      • :是C++的标准输出、输入流的库函数头文件;其函数的声明与定义在,命名空间std中。
      • std::cout:是C++的标准输出函数;可以通过插入运算符  来读取各种类型的数据。
      • std::endl:用于在输出流中插入一个换行符,并刷新输出缓冲区;这意味着它不仅仅是插入一个换行符(\n),还会确保所有等待在缓冲区中的输出都被发送到它们的目的地(如屏幕)。
      • :流提取符号,用于读取数据。
      • C++的cout与cin,会自动识别数据格式,无需,我们再像C语言的printf,scanf一样,要注意每个数据类型对应的占位符。

        三、缺省参数

        • 定义:所谓缺省参数,是针对函数形参形式来讲的;在函数声明或定义的时候,我们可以直接给形参赋值。当函数调用的时候,如果对应的实参没有被提供,那么将使用这些缺省值;反之则使用被提供的实参。(缺省参数又叫默认参数)
        • 函数声明与实现分离的时候,不能重复给缺省参数,且规定只能在函数声明的时候,给缺省参数。
        • 缺省参数分为全缺省,或半缺省;全缺省就是函数每个形参都又缺省参数,半缺省就是函数每个形参不全部都是缺省参数。
        • C++规定,半缺省参数,只能从右向左给;且函数调用的时候,必须从左向右给值,不能跳跃给值。
        • 错误使用案例,还请大家敲入合适的代码,进行测试;下面只展示正确的使用方法,以及函数的行为。

          C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

          四、重载函数

          • 定义:在相同域中,函数名相同,但形参不同的两个或两个以上的函数构成重载函数;
          • 重载函数特征1:函数名相同,形参个数不同;
          • 重载函数特征2:函数名相同,形参类型不同;
          • 重载函数特征3:函数名相同,形参顺序不同;
          • 注意事项:不能通过返回值的不同来定义重载函数
          • 优势:允许开发者通过相同的函数名,实现形参类型、个数不同,但功能类似的函数;这提高代码的可读性,增加了代码的灵活性;同时函数调用也会显得便利。

            //  形参个数不同

            void ZMH(int a, double b) { ; }

            void ZMH(int a, double b, int c) { ; }
            //  形参类型不同

            void ZMH(int a, double b) { ; }

            void ZMH(int a, int b) { ; }
            //  形参顺序不同

            void ZMH(int a, double b) { ; }

            void ZMH(double b, int a) { ; }

            //  不能通过返回值的不同来定义重载函数

            void ZMH(int a, double b) { ; }

            int ZMH(int a, double b) { ; }

            C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

            //  重载函数与缺省参数不恰当的混用,可能存在歧义

            void ZMH() { ; }

            void ZMH(int a = 4) { ; }

            问:上面两组函数,构成重载吗?

            答:构成

            问:调用ZMH();的时候,是执行哪一个函数呢?

            答:编译器不知道执行哪一个函数,会报错。

            C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

            五、引用

            1.引用的意义

                    讲引用的之前,先插入一个话题:周树人与鲁迅的关系;在革命时期,周树人写的文章很多都是讽刺社会的黑暗,以及国民政党的昏庸,百姓思想的封建。可反动势力,会容忍别人的诋毁吗?当然不会,倘若周树人直接以本名去当文章的作者,说不定上午刚发布完文章,下午反动势力,就闯进家门逮捕了;于是周树人就想着,我能不能取一个别名,去发布文章呢?这样不但降低了被逮捕的风险,而且也能实现自己的目标。

                    而C++的引入的引用,其价值,与周树人使用“鲁迅”这一笔名来发表文章,在某种意义上是相似的——都是为了避免直接暴露身份或对象,从而达到更安全、更灵活地执行目的的效果。

            2.引用的定义   
            • 引用并非是创建一个新变量,而是引用对象起一个别名,不占用内存空间
            • 我们可以通过引用,直接去操作引用对象。
            • 引用,可以用在函数的形参,函数的返回值,以及对某一局部变量直接使用引用。
            • 一个引用对象,可以有多个引用。
            • 引用必须初始化。(指针是推荐初始化,但可以不初始化)
            • 引用只能选择一个实体对象。(指针可以随意更改所指向的对象)
              3.引用的使用

                      我们在知道了引用的的重要性和概念之后,我们该如何正确使用引用呢?C++复用了C语言中的取地址操作符——&;在类型之后使用'&'则为引用。 type& 别名 = 引用对象;下面将通过代码例子进行进一步的理解。 C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)C++:C与C++的衔接课(C++基础知识,还请点赞收藏❤)

              4.const 引用
              • const type& 别名 = 引用对象。
              • const引用可以接受const对象,和普通对象,但普通的引用不能接受const对象——这遵从于权限不能放大,只能缩小。
              • 临时对象:程序运行时,会在内存开辟一个临时空间,去存储表达式求值的结果,称为临时对象,且临时对象具有常数性。
              • const引用可以接受临时对象,从而达到延长其生命周期的效果。
                5.引用的优势
                • 引用可以做函数参数和返回值,减少拷贝提高效率;
                • 引用传参,可以实现指针传参一样的效果,但指针要通过解引用才能访问到对象;
                • 引用,是对引用对象起别名,这使得代码更加的直观,和安全。

                  六、inline

                  • 函数声明与定义一起的时候,在其前面加上inline关键字,使得函数在调用的时候,并不会去建立函数栈帧,而是直接在调用函数的内部,将被调用函数的代码展开。这样减少了函数创建栈帧的效率,提高的代码运行效率,此函数称为内联函数。
                  • 在函数前面加上inline关键字,并非都被编译器所认可;递归函数、有些代码片段较长的函数,不触发内联函数的的机制。一般情况下,函数体小而简单,编译器才会进行内联函数的操作。
                  • inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。

                    七、nullptr

                    • 在C语言中,C++98中,官方将宏NULL,当作空指针的符号,有些情况是void* 类型的0,而有些情况只是0。
                    • C++中,void* 类型指针,不能隐式转换为其它类型的指针。
                    • 因此在某些函数重载的时候,NULL是隐形转换为整型0时候,是对于调用重载函数是存在歧义的;而void* 类型的0,编译器会报错。
                    • 所以C++11引用的nullptr关键字,此关键字总能被转换为任意类型的指针。
                    • 所以nullptr当作空指针,比NULL更具有安全性。
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]