c++语法(模板初阶+类和对象部分知识点)

news2024/12/23 6:30:27

1:泛型编程

2:模板

        2.1:函数模板

        2.2:类模板

3:const成员函数与非const的区别

4:构造函数之初始化列表

        4.1:初始化列表语法及其应用

        4.2:explicit关键字

5:static成员变量,static成员函数


1:泛型编程

        首先在提出泛型编程前我们先来看一下的代码(关于swap函数)。

void swap(int& x,int& y)
{
    int tmp=x;
    x=y;
    y=tmp;
        
}

void swap(double& x,double& y)
{
    double tmp=x;
    x=y;
    y=tmp;
        
}
void swap(char& x,char& y)
{
    char tmp=x;
    x=y;
    y=tmp;
        
}

.......

        我们知道因为c++支持函数重载所以我们能实现swap函数针对不同类型进行交换,但是上面不同swap函数的代码实现是非常相似的、冗余的除了类型不同,其他的代码实现逻辑是一样的。那么这样我们开发的时候效率可能会变低,代码的可维护性比较低,一个出错则其他的全部出错。

        所以我们的c++提供了一种编程技术,泛型编程:编写与类型无关的通用代码,是代码复用的手段。模板是泛型编程的基础。

   2:模板

        对于模板的理解:我们可以这样理解,模板与我们生活中的模具类似,模板只需要提供一份代码就能让编译器自动推演生成对应的具体类型函数

        模板可以分为:函数模板与类模板

        2.1:函数模板

               函数模板代表一个函数的家族,函数模板与具体类型无关。在使用时会被编译器实例化成具体类型的函数版本。

                语法:(关键字)template<typename  T1,typename T2.......>

                                     函数返回值  函数名(函数参数)   

                如下面的代码:

        


template<typename T1>
void Swap(T1& x,T1& y)
{
    T1 tmp = x;
    x = y;
    y = tmp;
}

                

        如上图我们所写的程序,我们相当于只写了一份函数模具,在编译器的处理下会生成两个不同版本的Swap函数,这两个函数调用时候的并不是同一个函数。

        T1:被称为模板参数,定义的时候可以有多个模板参数,typename可以与class替换。

注意:一个模板参数只能被实例化成一种类型,通常被实例化第一次传参的类型。

        

class与typename可以相互使用。

函数模板的原理:函数模板不是函数,本质是我们写的模具,在使用的时候会被编译器生成不同的函数,本质是让编译器做的更多,我们只需要写一份就行。

        如下图swap函数模板实例化被编译器

        在编译器编译阶段,编译器需要根据传入实参的类型从而生成出对应类型的函数以供调用。

        函数模板在使用的时候,模板参数必须被实例化。

        

        函数模板实例化:用不同类型参数,生成不同的函数。

        有两种方式:隐式实例化,显示实例化。

        隐式实例化:编译器根据实参来自动实例化。

        显示实例化:语法:函数名<类型>(实参),有些场景必须使用显示实例化,假如我们无参数的函数,或者有但是与模板参数无关。

        

swap<int>(x,y);
swap<double>(x,y);

被指定准确的类型后,如果变量不是相应的类型那么就会自动隐式类型转换成相应的类型。

比如说  x是double类型,y是int类型。那么调用swap<int>(a,b)的时候,a会隐式类型转化为int类型。

 模板参数的匹配问题

        一个具体的函数可以与模板函数同时存在比如说以下代码:

        

int Add(int left, int right)
{
 return left + right;
}
 
// 通用加法函数
template<class T>
T Add(T left, T right)
{
 return left + right;
}

void Test()
{
 Add(1, 2); // 与非模板函数匹配,编译器不需要特化
 Add<int>(1, 2); // 调用编译器特化的Add版本
}

        上面就是模板函数与非模板函数同时存在的咧子,匹配规则:

        1:有匹配的就不用生成对应的模板函数了。

        2:无匹配的并且满足对应的函数模板语法就会使用模板函数生成对应的类型函数。

        模板函数不允许自动类型转化,但普通函数可以。

        这里的意思是指假如我们没有匹配的非模板函数,那么编译器在生成模板函数的时候不会将我们的实参从一种类型转化成为其他类型。


2.2:类模板        

语法:template<class T1,class T2,class T3.........>

        class 类模板名   {类内定义}

比如我们所写的Stack类:

template<class T1>
class Stack
{
public:
    Stack(int capacity =4)
    {
        _a=new T1[capacity];
        _top=0;
        _capacity=capacity;   
    }
    ~Stack()
	{

		delete[] _a;
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
    //
    ......

private:
    T1 *_a;
    int _top;
    int_capacity;
}

   在这里我们就实现了一个类模板了,能通过显示实例化定义不同的Stack对象。

   类模板的实例化只能通过显示实例化进行。

如下图:

        


3:const成员函数与非const的区别

        首先const成员函数是类里面特有的,将const修饰的成员函数称为const成员函数。

        主要修饰的是对象创建后的函数,既构造函数不受这个const的影响

        实际这个const修饰的是隐藏的this指针--->const Stack* this,表示的是this指针所指向的成员变量不能被修改。

const成员函数,是在类内部成员函数最后加一个const修饰的,这里的const给的是this指针-->const Stack* this

假设我们const是对象,此时就不能调用非const成员函数。因为权限不能放大  const--->非const 权限放大,非const-->const权限缩小,权限可以缩小/平移但是不能放大,因此上面的st2去掉用非const函数属于权限放大不能执行,所以编译就不通过。

因此我们对于const成员函数的定义规则如下:

1:对于那些需要修改成员变量内容的成员函数(构造函数除外)不能使用const。

2:能定义成const成员函数就尽量定义成const成员函数,这样非const对象也能调用const成员函数。


4:构造函数之初始化列表

        我们前面已经学过了构造函数的语法了,我们知道我们在定义构造函数的语法,但是我们了解的还不够,所以我们还得学一个语法:构造函数的初始化列表

        首先我们知道:类在实例化(定义)的时候才可以开辟空间,而我们的初始化列表则是每个变量定义的地方,我们先来通过代码看看初始化列表的语法是怎么样的。

这样的就是初始化列表的写法:冒号开始,逗号分开,符号中间填成员变量初始化内容

对于初始化列表的理解:

        1:一些必须得定义的成员变量必须在初始化列表中进行初始化函数体内不能进行初始化,比如 引用&,const 成员变量自定义类型无默认构造函数(可以不需要传参数的)

        2:我们的构造函数先走初始化列表在走函数体内初始化,我们尽量使用初始化列表初始化,因为自定义类型成员变量一定会先走初始化列表初始化。

        3:不能完全放弃函数体内初始化,因为初始化列表有些功能是做不到的,比如说开空间失败的时候,我们就需要使用函数体内来判断是否开辟失败了。因此初始化列表与函数体初始化是可以混着用的。

        4:初始化列表如果有没定义的成员变了,那么对于内置类型初始化列表会给缺省值,而自定义类型成员我们回去调用他的初始化列表。

  特殊的语法:初始化列表初始化的顺序与成员变量的声明顺序相同。

这个代码的值分别是多少呢?

如果我们按照从上往下的走那么我们的答案因该是:  1 1

但是我们的答案确实  1  随机值

因为我们的_a2先声明的,所以我们也先走_a2(a1),而此时_a1是随机值所以我们就得到了_a2是随机值。

        因此我们需要记住:初始化列表初始化的顺序与成员变量声明的顺序相同。


4.2 explicit关键字

        在我们语法当中,我们的内置类型对象可以隐式类型转换成为自定义类型对象,而支持这样转化的语法是当我们构造函数只有单参数构造函数(支持传一个参数或多参数缺省值的也可以)发生这样的转化,如果我们不想要这个隐式类型转化发生那么我们就可以在构造函数前面加上explicit键字,防止类型转化的发生。

如下面的代码:

那么为什么这种写法成立呢?

其实本质上是先用3去构造了一个A类型的临时对象,然后在用这个临时对象去拷贝构造a2.

这种隐式类型转化是非常广泛使用的,在后面的STL数据结构中会涉及。比如说push_back(1);


5:static成员变量与成员函数


      static成员变量:属于类的成员变量,并不只属于某个对象,但是是每个对象可以调用他.

      声明与定义是分离的,不能在类内定义,在类外也不需要static关键字,得在类外并且指定类域找到这个成员变量定义,静态成员变量不走初始化列表。

        访问静态变量的时候:  类名::成员变量      对象.成员变量

      计算的类的时候不需要计算static成员变量的大小。因为static成员变量的定义是在类外定义的。

     static成员函数:静态成员函数无this指针,不能访问任意非静态成员。

总结:静态成员变量本质上就是受访问限定付与类域限制的全局变量,静态成员函数本质是受类域和访问限定符影响的全局函数无this指针。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA随记——VIVADO中ASYNC_REG指令

参考文章&#xff1a;Vivado综合属性系列一、ASYNC_REG_asyncregtrue-CSDN博客 -很棒棒的 跨时钟域设计&#xff08;CDC&#xff09;是个老生常谈的问题&#xff0c;其场景很多很杂&#xff0c;其中一个比较为人熟知的就是单bit信号从慢时钟到快时钟所采用的两级寄存器处理的…

抖音矩阵系统源码搭建短视频批量剪辑矩阵分发,可开源或oem

打造多语言短视频平台&#xff1a;技术实施方案揭秘 在短视频矩阵系统技术开发实施方案中&#xff0c;数据库设计是基础环节。首先&#xff0c;需要建立语言包数据库表并填充初始文本数据&#xff0c;如英语和中文的常用语。接着&#xff0c;要设计高效的数据库连接和数据访问接…

erlang学习:Linux命令学习3

shell基本输出 创建一个test.sh文件&#xff0c;并开放他的权限&#xff0c;之后向其中编辑以下内容 touch test.sh chmod 777 test.sh vim test.shecho "hello linux"之后运行相应shell程序得到输出 ./test.sh变量 单引号特点&#xff1a; 单引号里的任何字符都…

【Joint Receiver Design for ISAC】Neyman person | Gaussian | MMSE estimator |

【1】统计信号处理 Neyman-Pearson criterion pp 425 【1】 R c E { g x ( n ) x ( n ) H g H } σ 2 I g g H σ 2 I , \mathbf{R}_c\mathbf{E}\{\mathbf{g}x(n)x(n)^H\mathbf{g}^H\}\sigma^2\mathbf{I}\mathbf{g}\mathbf{g}^H\sigma^2\mathbf{I}, Rc​E{gx(n)x(n)HgH}σ2…

sheng的学习笔记-AI-归纳逻辑程序设计(ILP)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 规则学习&#xff08;rule learning&#xff09;: sheng的学习笔记-AI-规则学习&#xff08;rule learning&#xff09;-CSDN博客 一阶规则学习&#xff1a; sheng的学习笔记-AI-FOIL(First-Order Inductive Learner)-CSD…

计算机组成原理(笔记4)

定点加减法运算 补码加法&#xff1a; 补码减法&#xff1a; 求补公式&#xff1a; 溢出的概念 在定点小数机器中,数的表示范围为|&#xff58;|<1。在运算过程中如出现大于1的现象,称为 “溢出”。 上溢&#xff1a;两个正数相加&#xff0c;结果大于机器所能表示的最…

全栈开发(一):springBoot3+mysql初始化

1.开发环境准备 1.开发工具 2.jdk下载 官网下载java17 3.java环境变量配置 用户变量&#xff1a; ①.JAVA_HOME ②.path 4.mysql下载 b站随便搜 5.新建项目 6.maven配置 可以下载zip放到目录里 这里是配置好的 repository文件夹&#xff1a;为maven提供下载的文件存放…

TSRPC+Cocos

TSRPC文档: https://tsrpc.cn/docs/get-started/api.html 创建 先创建一个默认的会话项目&#xff0c;找一个文件夹在控制台运行以下代码&#xff1a; npx create-tsrpc-applatest first-api --presets browser # 或者 yarn create tsrpc-app first-api --presets browser运…

SpringBoot3快速入门(持续更新)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;JavaWeb关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ SpringBoot是什么 SpringBoot它可以帮我简单&#xff0c;快速地创建一个生产…

Java | Leetcode Java题解之第417题太平洋大西洋水流问题

题目&#xff1a; 题解&#xff1a; class Solution {static int[][] dirs {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};int[][] heights;int m, n;public List<List<Integer>> pacificAtlantic(int[][] heights) {this.heights heights;this.m heights.length;this.n…

实战19-详情页UI4等分

import { PADDING } from ../../constants/size; import rvp from ../../utils/resposive/rvIndex;Component export default struct SearchFilter {build() {Row() {Row({ space: rvp(6) }) {Text("位置").fontSize(rvp(14)).fontColor(#333333)Image($r(app.media.…

string map练习

to_string 在<string>头文件的std命名空间中 要格式化写浮点型入字符串用 2.map 直接尾插 set,map同方法&#xff0c;map只是把键变为pair键值对 4. string的花括号隐式类型转换不能字母个数字母&#xff0c;会被认为是初始化列表&#xff0c;而不是个数加字母的隐式类…

CSS简明通俗教程

CSS简明通俗教程 1. CSS简介 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种样式表语言。CSS用于描述HTML或XML&#xff08;包括SVG或XHTML等XML方言&#xff09;文档的呈现方式&#xff0c;它有自己的语法规则和逻辑&#xff0c;用于控制网…

【计算机网络】传输层协议TCP

目录 一、重新理解封装和解包二、TCP协议段格式三、确认应答(ACK)机制四、超时重传机制五、连接管理机制六、理解TIME_WAIT状态和CLOSE_WAIT状态七、流量控制八、滑动窗口九、拥塞控制十、延迟应答十一、面向字节流十二、粘包问题 一、重新理解封装和解包 在网络协议栈中&…

SRS流媒体服务器在宝塔面板下的安装

目录 一、安装 1、安装Docker 2、安装srs 二、测试 1、进入后台 2、推流 3、播放测试: (1)网页 (2)拉流 之前一篇文章,我们介绍了SRS流媒体服务器在CentOS下的安装,安装流程还是比较麻烦且耗时的,其实SRS支持Docker部署,今天我们介绍在宝塔面板的Docker中部署…

leetcode第80题:删除有序数组的重复项(||)

给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 说明&…

孤独伤感视频素材哪里找?分享热门伤感短视频素材资源网站

你是不是也经常在抖音上刷到很火的伤感视频&#xff0c;那么伤感视频素材都在哪里可以下载呢&#xff1f;作为一名从业多年的视频剪辑师&#xff0c;今天就跟大家聊聊那些可以下载伤感素材高清无水印的网站&#xff0c;如果你也在苦苦找寻伤感素材&#xff0c;快来看看吧&#…

JEDEC DDR4 SRAM standard

本文主要记录DDR4与DDR3有较大差异的点。 2.DDR4管脚 信号 类型 描述 C0,C1,C2 input chip IDchip ID仅用于通过TSV&#xff08;硅通孔&#xff09;选择3DS堆叠组件的2层、4层、8层高堆栈中的每一片&#xff0c;chip ID被视为命令代码的一部分。 ACT_n input 激活命令…

【小程序】uniapp自定义图标组件可动态更换svg颜色

组件描述 通过图标名称加载对应svg&#xff0c;size参数调整图标大小&#xff0c;color参数调整图标颜色 解决思路&#xff1a; 存svg获svg&#xff0c;对象方式正则替换svg的fill值&#xff0c;不改变源文件&#xff0c;通过base64直接加载缓存svg源文件&#xff0c;避免重…

在VMware16中安装Windows 10:完整教程

在VMware中安装Windows 10&#xff1a;完整教程 1.安装环境准备2.创建虚拟机 1.安装环境准备 1.虚拟机: VMware-workstation-full-16.2.2-19200509 2.系统镜像:win10 2.创建虚拟机 1.自定义 2.下一步 3.稍后安装系统 3.默认下一步 4.虚拟机取名和选择存放路径(按需更改…