首页 > 其他分享 >day02

day02

时间:2023-08-25 16:57:44浏览次数:36  
标签:调用 函数 day02 引用 内联 指针 构造函数

一、函数重载     1、什么是函数重载         在同一作用域下,函数名相同,参数列表不同的函数构成重载关系         函数重载与返回值的类型、参数名无关         与作用域是否相同,以及参数列表的数量、参数类型、常属性不同等有关     2、C++如何实现函数重载的?         通过g++ -S 生成汇编代码可知,编译器会把函数的参数类型进行缩写后,追加到函数名的末尾,形成新的函数名,既是进行了换名操作,确保编译结果函数名不重复     3、extern "C"         因为通过C++编译器编译函数、调用语句时,会变成换名后的名字去调用,但是项目中有可能需要去调用已经通过C编译器编译好的函数,它们是没有换名的,因此会调用失败         因为大部分情况下,C编译好的文件无法重新使用C++编译器重新编译,所以只能想办法让C++编译器在调用C编译的函数时不要换名         通过 extern "C"{xxx} 让C++编译器按照C语言的格式编译函数,从而让调用语句与被调用函数同名,这样就可以正确地调用C标准库、系统函数     4、重载和隐藏         在不同作用域下,同名函数构成隐藏     5、参数类型如果不匹配         当调用函数时,编译器会优先调用类型最匹配最精确的版本函数,如果没有最正确的则会先做类型转换后再匹配,但如果没有能够进行类型转换、类型匹配的版本最后也会报错         但是不建议通过类型转换去调用函数,因为转换情况跟编译器有关
二、默认形参     1、什么是默认形参         在C++中可以给函数的参数设置默认值,当函数被调用时如果调用者提供了实参,则使用实参调用,如果没有提供则使用默认值调用     2、默认形参要靠右         如果函数有多个参数,并设置了默认参数,要遵循从右往左依次设置默认形参     3、只能在函数声明中设置默认形参         如果函数声明与定义分开实现,只能在函数声明中设置默认形参,否则语法错误     4、默认形参可能会影响函数重载         如果对函数进行了重载,又设置了默认形参,调用时可能会有冲突和歧义,调用失败         因此对于重载过的函数设置默认形参时一定要谨慎
三、内联函数     1、普通函数         普通函数会被编译成二进制指令,存储在代码段中,调用语句会生成一条跳转指令,当程序运行到调用语句时,会跳转到该函数在代码段中对应的位置执行,执行结束后会返     2、什么是内联函数         内联函数也会被翻译成二进制指令,但调用语句不会生成跳转指令,而是直接把内联函数的二进制指令进行替换,就没有跳转和返回,而是直接执行二进制指令,这种函数称为内联函数     3、显式内联和隐式内联         显示内联:             在函数的返回值前加 inline 该函数就以内联函数的机制调用         隐式内联:             在结构、联合、类中的成员函数会自动被当作内联函数来处理             注意:如果在结构、联合、类中声明成员函数,但是在外面定义,则不会当作内联处理         注意:函数是否被内联由编译器以及它的优化等级来决定,加 inline 只可能影响它的决定         注意:g++默认优化等级 -O -O1 下所有的内联函数都会当成普通函数处理                             -O2 -O3 的优化级别下,甚至普通函数都可能会被当作内联函数处理             注意:C99 也支持 inline     4、内联的适用条件         优点:节约了函数传参、跳转、返回的时间,提高代码的运行速度         缺点:当被多个位置调用时,那么同样的二进制指令会被拷贝多份,产生了冗余,导致可执行文件明显增加         使用条件:             1、适合内容简单且同一位置频繁调用的函数             2、不适合内容多、且多个位置、较少调用的函数,因为节约的时间还弥补不过牺牲的空间             3、带有递归属性的函数无法内联,编译器会自动忽略     5、*内联函数和宏函数的相同点、不同点*         相同点:             都是采用空间换时间的策略提高程序的运行速度,减少函数调用跳转的耗时         不同点:             1、宏函数不是真正的函数,只是语句替换,不会对参数进行类型检查,也没有返回值、安全性低             2、内联函数是真正的函数,严格检查参数类型、有返回值,安全性高
四、引用     什么是引用:引用就是一种取别名的机制     (回顾)为什么要使用指针:             1、跨函数共享变量(输出型参数)   ,引用可替代             2、提高传参效率                ,引用可替代,效率比指针还高,不拷贝字节             3、配合堆内存使用              ,不能替代只能使用指针             4、配合字符串使用              ,string类可以替代     引用使用格式:         类型名& 别名 = 数据;
    什么情况下使用引用:         1、跨函数共享变量,引用比指针更安全(无需直接操作地址空间、不存在空引用,也极少出现野引用)、也比指针更方便(无需取地址、解引用)         2、提高传参效率,引用的效率比指针还高,指针最起码还要传递4(8)字节的地址编号,但是引用一个字节都无需传递,但是引用和指针一样都有被修改的风险,因此为了保护目标需要增加 const         使用引用需要注意的事项:         1、引用必须初始化,所以不存在空的引用         2、可以引用右值,但是必须使用 const 修饰引用         3、引用不能中途更改引用的目标         4、函数的返回值类型可以是引用类型,但是不能返回局部变量的引用
                                            **面试常考题:指针与引用的相同点和不同点**                                     相同点:                                         1、都可以跨函数共享内存,都可以提高函数的传参效率,也需要const保护                                         2、可以定义数组指针,也可以定义数组引用                                             int arr[5]={1,2,3,4,5};                                             int (*arrp)[5]=&arr;                                             int (&hehe)[5]=arr;                                         3、可以定义函数指针,可以定义函数引用                                             void (*fp)(void) = func;                                             fp();                                             void (&xixi)(void) = func;                                             xixi();                                       不同点:                     指针是一种特殊的数据类型,使用它可以定义指针变量,指针变量中存储的是整型数据,该数据代表了内存的编号(地址),可以通过这个编号访问到对应的内存                                         1、引用是一种取别名的机制,而指针是一种数据类型                                         2、引用不需要额外的存储空间,指针需要4(8)字节用于存储内存地址                                         3、指针可以不初始化,引用必须初始化                                         4、指针有空指针,但没有空引用                                         5、指针可以更改指向的目标,但引用不可以                                         6、指针可以配合堆内存使用,而引用不行                                         7、可以定义指针数组,但不能定义引用数组
五、C++的强制类型转换     C语言原来的强制类型转换依然可以在C++中继续使用         (新类型)数据 注意:强制类型转换都只是得到一个临时结果,数据原来的类型不会改变     为什么C++要重新设计强制类型转换?         因为C语言的强制类型转换虽然自由度高但是非常危险     为什么C++之父设计强制类型转换设计得很复杂、使用很麻烦?         因为他认为只有在程序设计不合理的情况下才需要强制类型转换,之所以设计复杂就是不想让调用者使用,而是反思、重新设计自己的代码         1、静态类型转换     static_cast<目标类型>(原数据)     目标类型和原数据类型之间必须有一个方向能完成自动类型转换,否则出错     2、动态类型转换     dynamic_cast<目标类型>(原数据)     目标类型和原数据类型之间必须存在继承关系,并且目标类型必须是指针类型或者引用类型,否则出现错误     3、去常类型转换     const_cast<目标类型>(原数据)     目标类型必须是指针或引用,而且除了const属性不同,其他都必须相同,否则报错     4、重解释类型转换     reinterpret_cast<目标类型>(原数据)     只能把整数转成指针类型,或者把指针转成整数,否则会出错
六、面向对象和面向过程     面向过程:         关注如何解决问题,以及解决问题的步骤
    面向对象:         关注解决问题的 '人'-'对象' ,以及实现能解决问题的 '对象'                 抽象:先找出(想象)能解决问题的'对象',分析该对象解决问题所需要的属性(成员变量)和行为(成员函数)
        封装:把抽象的结果封装成一个类类型(结构),并给与类的成员变量和成员函数设置相对应的访问控制权限(public,private,protected)                 继承:             1、在封装类之前先考虑现有的类是否能解决部分问题,如果有则可以通过继承,只需要在此基础上扩展即可,从而缩短解决问题的时间             2、把一个复杂的大问题拆分成若干个不同的小问题,给每个小问题设计一个类去解决,最后把这些类通过继承合并成一个能解决大问题的类,从而减低问题的难度
        多态:               发出一个指令,系统会根据实际情况指向不同的操作,这种特征就称为多态(一个指令多种形态)                 比如重载过的函数、当调用函数时会根据参数的不同调用不同的版本,具体调用哪个版本在编译期间就确定,因此称为编译时多态         注意:面向对象的细节的本质上还是面向过程,因此面向对象不是解决问题的捷径,而是以更高的维度去思考问题
七、类和对象     什么是类和对象         类是由程序员设计的一种数据类型,里面包含有成员变量和、成员函数         而对象就是类的实例化,可以理解为使用类类型创建的变量,创建的过程就叫做实例化
    类的设计和对象的实例化:         class 类名         {             成员变量; //类中默认属性是private私有         public:             成员函数;         };
        对象的实例化:             方法1:类名 类对象名;             方法2:类名* 类对象名_p = new 类名;
    类的声明、实现、使用:         1、在头文件中声明:             class 类名             {                 成员变量;             public:                 返回值 成员函数名(参数列表);             };         2、在源文件中实现成员函数             返回值 类名::成员函数名(参数列表)             {                 // 在成员函数中可以直接使用成员变量、成员函数                 //不需要使用 . -> 来表示访问             }         注意:如果类的内容不多,也可以直接在头文件中把成员函数实现
八、访问控制限定符     private         私有的,被它修饰的成员只能在类内访问,这是类的默认访问属性         设置为私有的是为了对类进行保护,一般成员变量设置为私有     public         公开的,被它修饰的成员可以在任意位置访问         一般会把成员函数公开     protected         保护的,被它修饰的成员只能在本类内和它的(直接)子类中访问,但不能在类外访问
九、构造函数     构造函数就是与类名同名的成员函数,当实例化对象时,它会自动执行     当构造函数执行完后,对象才完成实例化     任务:一般负责对类对象进行初始化     class 类名     {         int* p;     public:         类名(参数类型)         {             p = new int;         }     }
    1、构造函数必须是public,否则无法创建对象     2、构造函数可以重载,可以有多个版本的构造函数(无参、有参)     3、带参数的构造函数的调用         类名 对象名(实参) //使用实参来调用有参构造         类名* 对象名 = new 类名(实参) //使用实参来调用有参构造     4、默认情况下编译器会自动生成一个什么都不干的无参构造函数,但一旦显式地实现了构造函数,就不再自动生成该无参构造函数     5、如果给有参构造设置了默认形参,实例化对象时可以出现类似无参构造的语句,但实际是调用有参构造     6、构造函数没有返回值     7、不能使用malloc给类对象分配内存,因为它不会调用构造函数

十、析构函数     任务:析构函数一般负责对类对象内容进行收尾工作,例如:释放资源,保存数据等     当类对象销毁时,会自动执行     class 类名     {         int* p;     public:         类名(参数类型)         {             p = new int;         }         ~类名(void)         {             delete p;         }     }     1、析构函数必须是public     2、析构函数没有参数、没有返回值、不能重载     3、当类对象生命周期完结,被操作系统自动释放(栈),或者通过 delete 手动释放(堆),才会调用析构函数     4、构造函数必定执行,但析构函数不一定会执行     5、不能使用free去销毁类对象,因为不会调用析构函数     6、如果没有显式地实现析构函数,编译器也会自动生成一个什么都不做的析构函数
十一:初始化列表     初始化列表是属于构造函数的一种特殊语法,只能在构造函数中使用     class 类名     {         const 成员1;         成员2;     public:         类名(参数列表) : 成员1(val),成员2(val)  //初始化语句 val可以是变量也可以是常量         {         //    成员1 = val; 属于赋值语句 不是初始化 带const属性的成员就无法赋值         }     };
    注意:         1、初始化列表是先于构造函数执行,初始化列表执行时,类对象还没有实例化完成,因此他是一种给const属性成员变量初始化的最佳方案         2、当参数名与成员名相同时,初始化链表可以分辨出来,可以同名         3、当成员中有类类型,该成员的有参构造函数可以在初始化列表中调用

标签:调用,函数,day02,引用,内联,指针,构造函数
From: https://www.cnblogs.com/ymy1/p/17657364.html

相关文章

  • java基础数据类型-int类型-day02
    目录1.变量的命名2.常量3.变量4.进制4.1进制转换4.2整型数据类型1.变量的命名记住一点:不可以以数字开头类名:首字母大写的驼峰体变量名,方法名:首字母小写的驼峰体包的名字:与python语言一样全部小写2.常量整形:123实数型:3.14字符:‘a’字符串:"abc"布尔值:truefalse......
  • day02
    TCP服务端处理多客户端任务:  原来是通过开启子进程来服务不同的客户端,当客户端退出时就关闭该子进程多路复用:  使用一个进程(有且只有一个主进程)同时监控若干个文件描述符,这种读写模式称为多路复用  多用于TCP的服务端,用于监控客户端的连接和数据的收发  ......
  • 标准C++ -- day02
    一、函数重载什么是函数重载在同一作用域下,函数名相同,参数列表不同的函数构成重载关系函数重载与返回值类型、参数名无关与作用域是否相同,以及参数列表的数量、参数类型、常属性不同等有关#include<iostream>usingnamespacestd;voidfunc(intnum){cout<<"i......
  • JavaSE学习笔记day02
    面向对象一、面向过程和面向对象的思想面向过程的思想:将事情拆分成多个步骤,然后一步一步地完成即可。强调事情的具体步骤/过程。该思想常见于编码过程中的方法或者函数当中。比如:打扫教室(1)先拿到清洁工具(2)然后扫地(3)然后拖地(4)倒垃圾(5)归还清洁工具......
  • 网络编程day02--FTP协议
    封装socket网络通信模块-network原因:TCP、UDP客户端、服务端的操作流程固定,所以为了后期使用方便,把socket网络通信封装成网络模块任务:生成libnw.so共享库笔试、面试问题:回答原始函数讲项目:聊封装过程FTP协议FTP的独特的优势同时也是与其它客户服务器程序最大的不同点就在于......
  • day02
    一、内存管理  用户层  STL  智能指针/容器自动分配、释放  调用C++  C++  new/delete          调用C  C   malloc/free         调用POSIX/Linux  POSIX brk/sbrk     ......
  • day02 - 数组
    977. 有序数组的平方//双指针classSolution{public:vector<int>sortedSquares(vector<int>&nums){inti=0;intj=nums.size()-1;intk=j;vector<int>result(nums.size(),0);for(;i<=......
  • Java学习面向对象Day02
    面向对象Day02-继承一、继承1.1生活中的继承皇位继承------------------------儿子不需要打江山,可以直接坐江山努尔哈赤---------------------东三省做主的范围东三省皇太极-----------------------继承的努尔哈赤可以直接对东三省做主自己打下了内外蒙古做主......
  • 20天 hot 100 速通计划-day02
    双指针15.三数之和给你一个整数数组nums,判断是否存在三元组[nums[i],nums[j],nums[k]]满足i!=j、i!=k且j!=k,同时还满足nums[i]+nums[j]+nums[k]==0。请你返回所有和为0且不重复的三元组。注意:答案中不可以包含重复的三元组。示例1:输入:nums=[-......
  • Qt-day02
     调用重载的信号  #ifndefMAINWIDGET_H#defineMAINWIDGET_H#include<QWidget>#include<QPushButton>#include<QDebug>#include"subwidget.h"classMainWidget:publicQWidget{Q_OBJECTpublic:MainWidget(QWidget*par......