C++——基础

初学C++的时候,有没有想过,为什么C++支持重载,而C不支持重载呢??

其实,一个程序运行起来都要经过四步骤

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

预处理阶段会经过去注释,宏替换,头文件展开,条件编译... 

编译阶段会生成汇编代码,会经过语法分析,词法分析,语义分析,符号汇总...(像了解详细的可以去看看 《程序员的自我修养》,在它的第二章会详细讲解)


汇编阶段会将汇编生成二进制,然后在这一阶段生成符号表

链接阶段会合并段表,符号表的汇总和重定向。

  1. 实际的项目中,通常由多个头文件和源文件构成,然后通过编译链接,最后形成.o文件,如果为我们一个test.cpp调用了add.cpp中的add函数,在编译后链接前,.o的目标文件中没有add函数的地址,因为add函数是在add.cpp中的,所以add的函数在add.o中,那么怎么办呢??
  2. 链接阶段解决了这个问题,链接器看到了test.o调用了add.o中的add函数,但是没有add的地址,就会去add.o中的符号表中去找add的地址,然后链接到一起。
  3. 这时,链接器会通过函数名的修饰规则去找,而不同编译器的函数名修饰规则不一样。

这里用Linux中的gcc和g++来做例子:

这时回到我们一开始的问题,为什么C++支持重载呢???  就是因为通过C++可以通过函数名的修饰规则来区分,而C函数名修饰规则后,函数名都是一样的,所以不能重载。

 那么有一个问题,如果有两个函数,函数名一样,参数一样,但返回值不同,这是否能构成重载呢??
当然不能,因为编译器不能够通过返回值不同来判断是否构成重载。


引用:引用不是定义一个变量,而是给已存在变量取了一个别名,编译器不会另外开辟空间,而是和变量一起共用一个空间。

引用经常和指针来对比,而引用经常用来做返回值,这时因为用引用来做返回值,可以提高效率。

#include <iostream>
#include <time.h>
using namespace std;struct A
{int a[10000];
};A a;// 值返回
A TestFunc1()
{return a;
}// 引用返回
A &TestFunc2()
{return a;
}void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}int main()
{TestReturnByRefOrValue();return 0;
}

但有一个很重要的区别就是

  1. 语法程度上,引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
  2. 底层上来讲,引用的底层就是指针来实现的。

 类的6个默认成员函数:

构造函数:构造函数是一个特殊的成员函数,需要注意的是构造函数的工作是初始化对象。

而默认构造函数有三种:

  1. 用户没有显示实现的时候,编译器自动生成
  2. 用户显示实现,但是一个参数都没有(无参构造函数)
  3. 用户显示实现,参数全部都有缺省值(全缺省构造函数)

ps:这三种默认构造函数不能同时存在。如果2 3 同时存在,那么当一个类时空类的时候,它调用的时候就会存在歧义。

特征如下:

  1. 函数名和类名相同
  2. 没有返回值
  3. 对象实例化的时候会自动调用构造函数
  4. 构造函数可以重载

在创建对象的时候,编译器会自动调用构造函数,给每个成员赋初值,这时每个成员都会去走初始化列表。

初始化列表:以一个冒号开始,接着是一个逗号分割的数据成员列表,每个“成员变量”后面跟一个放在括号中的初始值或表达式。

class A
{A():_a(a),_b(b){}private:int _a;int _b;
};

当然每个成员在初始化的时候只能初始化一次,但有三种必须放到初始化列表中

  1. const成员变量
  2. 引用成员变量
  3.  自定义类型成员(且该类没有默认的构造函数)

析构函数:与构造函数相反,析构函数是在对象销毁时自动调用析构函数,完成对对象中资源的清理工作。

特征如下:

  1. 析构函数要在类名的前面 + ~
  2. 无参数无返回值
  3. 一个函数只有一个析构函数,最好变成虚函数,这样形成多态的一个条件。

拷贝构造函数:只有单个参数,该参数是对本类型的引用,当一个已经存在的对象初始化创建一个新对象的时候,会自动调用拷贝构造函数。

特征如下:

  1. 拷贝构造函数是构造函数的一个重载
  2. 拷贝构造函数的参数必须是本类型的引用,如果不加引用,会无限递归调用拷贝构造函数,最终会造成栈溢出。

编译器默认生成的拷贝构造函数是值拷贝,在某些场景是不能使用的,所以需要我们去深拷贝。

C++11增加了两个默认的成员函数:

  1. 移动构造函数
  2. 移动赋值运算符重载

针对移动构造函数和移动赋值运算符重载有写特定的要求:

  • 如果你没有自己实现移动构造函数,且没有实现析构函数,拷贝构造、拷贝赋值重载中的任何一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现了移动构造,如果实现了就调用移动构造,如果没有实现就调用默认的移动构造。
  • 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中
    的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内
    置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋
    值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造
    完全类似)

 赋值运算符重载:C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有返回值类型,函数名字以及参数列表,其返回值类型与普通的函数类型。

特征如下:

  1. 重载操作符必须有一个类类型参数
  2. 作为类成员函数,形参比操作数少1,这时因为第一个隐藏的参数是this指针
  3. .* sizeof :?  .  不能重载

我们来看一下string的赋值运算符重载,不难发现它的返回值是string&。

想一想为什么返回值会是引用呢??

  • 返回值如果是引用那么就是可以提高返回的效率,因为会少一次拷贝构造,有返回值是为了支持连续的赋值

参数是const T&,是因为这样可以支持左值或右值,传递引用也是为了提高效率。


explicit关键字:

构造函数不仅仅可以构造还可以初始化对象,对于单个参数或除第一个参数无默认值其余都有默认值的构造函数,还具有隐式类型的转换的作用。而explicit关键字的作用就是修饰构造函数,禁止构造函数去隐式类型的转换。


static成员:

用static修饰的成员变量叫做静态成员变量,用static修饰的成员函数,叫做静态成员函数。静态成员变量一定要在类外进行初始化。

class A
{static int _a;
};int A::_a = 1;

特征如下:

  1.  静态成员为所有类对象所共享,存在放静态区
  2. 静态成员变量必须在类外进行初始化,定义的时候不用加上static,类中只是声明
  3. 类静态成员可以通过 类名::静态成员 或者 对象::静态成员 来访问
  4. 静态成员函数没有this指针,不能访问任何的非静态成员变量
  5. 静态成员也受类修饰符的影响,受public,protect,private访问限定符的限制

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/168299.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Web——HTTP协议

目录 1. HTTP协议概述 1.1. HTTP数据传输格式 1.2. HTTP协议特点 2. HTTP 1.0和HTTP 1.1 3. HTTP请求协议 3.1. GET方式请求协议 3.2. POST方式请求协议 3.3. GET请求和POST请求的区别 4. HTTP相应协议 4.1. 响应状态码 如果两个国家进行会晤需要遵守一定的礼节。所以…

使用ffmpeg调用电脑自带的摄像头和扬声器录制音视频

1、打开cmd&#xff0c;执行chcp 65001,修改cmd的编码格式为utf8&#xff0c;避免乱码 2、执行指令ffmpeg -list_devices true -f dshow -i dummy,查看当前window的音频和视频名称 3、打开windows系统的"打开声音设置"–“麦克风隐私设置”–"允许应用访问你…

arduino 简易智能花盆

编辑器&#xff1a;arduino IDE 主板&#xff1a;arduino uno 传感器&#xff1a; 0.96寸的OLED屏&#xff08;四脚&#xff09; 声音模块 土壤温湿度模块 DS18B20温度模块&#xff08;这里用到防水的&#xff09; 光敏电阻模块&#xff08;买成三脚的了只能显示高低&#x…

金字塔原理小节

目录 第1章 为什么要用金字塔结构 一、归类分组&#xff0c;将思想组织成金字塔 二、奇妙的数字“7” 三、归类分组搭建金字塔 四、找出逻辑关系&#xff0c;抽象概括 五、自上而下表达&#xff0c;结论先行 第1章 为什么要用金字塔结构 如果受众希望通过阅读你的文章、听…

自动计算零售数据分析指标?BI软件表示可行

随着BI技术的飞速发展&#xff0c;借助系统来计算分析指标也不是什么难事&#xff0c;即便是面对组合多变的零售数据分析指标&#xff0c;奥威BI软件也依旧可以又快又精准地完成指标计算。 BI软件可以自动计算零售数据分析指标&#xff0c;如销售额、库存量、订单量等。在计算…

超简单的Linux FTP服务搭建教程

目录 前言1、检查vsftp是否已安装2、安装vsftpd3、启动ftp服务4、测试ftp服务5、上传文件配置总结 前言 本文记录了在Kylin Linux Desktop V10(SP1)系统上搭建FTP服务的过程。FTP是File Transfer Protocol的缩写&#xff0c;译为文件传输协议&#xff0c;是用于在网络上进行文…

Postman的环境变量和全局变量

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 多种环境&#xff1a;开发环境、测试环境、预发布环境、生产环境&#xff0c;可以用环境变量来解决。 今天的分享就到这里&a…

【Azure 架构师学习笔记】-Azure Storage Account(5)- Data Lake layers

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Storage Account】系列。 接上文 【Azure 架构师学习笔记】-Azure Storage Account&#xff08;4&#xff09;- ADF 读取Queue Storage 前言 不管在云还是非云环境中&#xff0c; 存储是IT 系统的其中一个核心组件。在…

Python和BeautifulSoup库的魔力:解析TikTok视频页面

概述 短视频平台如TikTok已成为信息传播和电商推广的重要渠道。用户通过短视频分享生活、创作内容&#xff0c;吸引了数以亿计的观众&#xff0c;为企业和创作者提供了广阔的市场和宣传机会。然而&#xff0c;要深入了解TikTok上的视频内容以及用户互动情况&#xff0c;需要借…

Win11专业版安装Docker Desktop,并支持映射主机的gpu

一、Windows环境下安装 Docker 必须满足: 1. 64位Windows 11 Pro(专业版和企业版都可以) 2. Microsoft Hyper-V,Hyper-V是微软的虚拟机,在win11上是自带的,我们只需要启动就可以了 二、下载Docker Desktop安装包 方式一:进入官网下载 https://docs.docker.com/desktop…

学习c#的第四天

目录 C# 变量 C# 中的变量定义与初始化 接受来自用户的值 C# 中的 Lvalues 和 Rvalues 不同类型变量进行运算 静态变量 局部变量 C# 常量 整数常量 浮点常量 字符常量 字符串常量 定义常量 扩展知识 Convert.ToDouble 与 Double.Parse 的区别 静态常量和动态常…

微软和Red Hat合体:帮助企业更方便部署容器

早在2015年&#xff0c;微软就已经和Red Hat达成合作共同为企业市场开发基于云端的解决方案。时隔两年双方在企业市场的多个方面开展更紧密的合作&#xff0c;今天两家公司再次宣布帮助企业更方便地部署容器。 双方所开展的合作包括在微软Azure上部署Red Hat OpenShift&#xf…