C++(面向对象编程)

思维导图

面向对象

1.面向对象思想

概念:面向对象编程(OOP)是一种以对象为基础的编程范式,强调将数据和操作数据的方法封装在一起。这就是上篇文章讲过的。面向过程是以“怎么解决问题”为核心,而面向对象思想在于“谁来解决问题”为核心。

特点:

1. 将操作的事物看成对象

2. 不需要自己亲自去做事,而是直接调用对象的行为完成需要的操作

3. 简化复杂的分步操作,提高编程效率

2.类和对象

类:类是一个概念,用于描述具体对象的特点,包括属性(数据)和行为(函数)。自定义类的命名必须使用帕斯卡命名法:所有单词的首字母大写。

        属性:也就是成员变量,具体的数据。

        行为:也就是成员函数,具体的函数,可以实现一定的方法。

对象:对象是依照类创建的实体,可以有多个,但是多个对象之间的数据是相互隔离的

一.类和对象的创建和使用

想象现在你就是上帝,你创造一只猫,它有年龄身高名字等基础属性,这些就是这个猫的“数据”,它还会奔跑,喵喵叫等,这些就是这个“数据”的动作,也就是“方法”,在C++中就可以把数据和方法封装在一起,这就有了面向对象的第一个属性----封装。这样一来,这个对象就不只是一个数据,还包含它的方法,就可以让这个对象完成一些特定行为,而不是我创造猫,我让猫叫,让猫跑,而是我创造了猫,让猫自己叫,自己跑。

1.创建类

#include <iostream>using namespace std;class Cat{
public:                //公有成员,可以在外部访问string name;        //属性string color;int age;double weight;void run(){          //行为:跑cout << "run for you" << endl;}void meow(int a){    //叫if(a == 8)cout << "miao miao" << endl;}void name1(){        //显示名字name = "mike";cout << name << endl;}
};int main()
{return 0;
}

2.创建对象

(1)栈内存对象:

只存活在最近的{}内,{}执行结束后自动销毁适合临时使用

 Cat cat1;

(2)堆内存对象:

使用new关键字创建使用delete关键字销毁如果不销毁持续存在导致内存泄漏。堆内存对象使用指针存储首地址使用->调用成员

Cat *cat2 = new Cat;

3.使用对象

当使用的pubulic修饰的类,可以直接在外部赋值,使用在对象后面加“.”就可以使用内部函数。

#include <iostream>using namespace std;class Cat{
public:                //公有成员,可以在外部访问string name;        //属性string color;int age;double weight;void run(){          //行为:跑cout << "run for you" << endl;}void meow(int a){    //叫if(a == 8)cout << "miao miao" << endl;}void name1(){        //显示名字name = "mike";cout << name << endl;}
};int main()
{//栈内存对象Cat cat1;cat1.name = "Mike";cat1.color = "yellow";cat1.age = 8;cat1.weight = 35.7;/*if(1){            //错误,创建的栈内存对象只能存活在最近的两个{}内,if一结束就不存在Cat cat1;}*/cout << cat1.name <<endl;cout << cat1.color <<endl;cout << cat1.age <<endl;cout << cat1.weight <<endl;cout << "#################" <<endl;cat1.run();cat1.meow(8);cat1.name1();cout << "#################" <<endl;//堆内存对象Cat *cat2 = new Cat;cat2->name = "Join";cat2->color = "red";cat2->age = 7;cat2->weight = 44.2;cout << cat2->name <<endl;cout << cat2->color <<endl;cout << cat2->age <<endl;cout << cat2->weight <<endl;return 0;
}

 

 二.封装

概念:上面代码结构体非常相似因为一个完全开放就是结构体实际上需要封装封装需要类中一些属性细节隐藏根据实际需求对外部开放调用读写接口

外部读取数据接口称为getter外部写入数据结构称为setter

核心思想:隐藏内部实现细节,通过公共接口控制访问

封装优势

        (1)数据保护(防止非法修改)

        (2)实现与接口分离

        (3)代码可维护性增强

#include <iostream>using namespace std;class Cat{
private:                // 私有成员(封装的核心)string name;string color;int age;double weight;
public:                  // 公共接口string get_name(){                //得到(返回)名字return name;}void set_name(string a){        //设置名字name = a;}string get_color(){            //得到(返回)颜色return color;}void set_color(string a){        //设置颜色color = a;}//尝试自己写一下其他操作
};int main()
{//栈内存对象Cat cat1;cat1.set_name("Mike");                    //设置名字cout << cat1.get_name() << endl;cat1.set_color("yellow");                //设置颜色cout << cat1.get_color() << endl;cout << "#################" <<endl;//堆内存对象Cat *cat2 = new Cat;cat2->set_name("Lisa");                    //设置名字cout << cat2->get_name() << endl;cat2->set_color("red");                //设置颜色cout << cat2->get_color() << endl;delete cat2;return 0;
}

 三.构造函数

构造函数(constructor)一种特殊成员函数

        (1)用于创建对象创建对象必须调用构造函数

        (2)如果一个类中程序员不写构造函数编译器自动添加一个无参构造函数

        (3)不写返回值类型返回一个创建对象

        (4)函数名称必须类名

构造函数主要功能创建对象完成对象数据初始化

可以和函数重载联合使用。

1.初始化构造函数:

#include <iostream>using namespace std;class Cat{
private:string name;string color;int age;double weight;
public:Cat(){                    name = "mike";color = "red";age = 4;weight = 33.5;}//函数重载Cat(string a,string b,int c,double d){name = a;color = b;age = c;weight = d;}void printf(){cout << name << endl;cout << color << endl;cout << age << endl;cout << weight << endl;}
};int main()
{//栈内存对象Cat cat1;                                        //不使用参数默认调用无参的构造函数cout << "#################" <<endl;cat1.printf();cout << "#################" <<endl;Cat cat2("Join","blue",8,66.2);                    //调用有参的构造函数cat2.printf();cout << "#################" <<endl;//堆内存对象Cat *cat3 = new Cat("Lisa","red",1,12.5);        //调用有参的构造函数cat3->printf();delete cat3;return 0;
}

2.构造初始化列表:

#include <iostream>using namespace std;class Cat{
private:string name;string color;int age;double weight;
public:Cat(){name = "mike";color = "red";age = 4;weight = 33.5;}//函数重载,构造初始化列表Cat(string a,string b,int c,double d):name(a),color(b),age(c),weight(d){/*name = a;color = b;age = c;weight = d;*/}void printf(){cout << name << endl;cout << color << endl;cout << age << endl;cout << weight << endl;}
};int main()
{//栈内存对象Cat cat1;                                        //不使用参数默认调用无参的构造函数cout << "#################" <<endl;cat1.printf();cout << "#################" <<endl;Cat cat2("Join","blue",8,66.2);                    //调用有参的构造函数cat2.printf();cout << "#################" <<endl;//堆内存对象Cat *cat3 = new Cat("Lisa","red",1,12.5);        //调用有参的构造函数cat3->printf();delete cat3;return 0;
}

3.调用方式:

(1)显式调用

明确指定使用构造函数,下面代码中cat1~3都是显式调用。

(2)隐式调用

没有明确指定使用构造函数,当隐式调用是一个字符串类型(Cat cat6 = "Lisa";),或报错,编译器没办法优化复杂这样复杂的情况。下面代码中cat4和cat5都是隐式调用。 

#include <iostream>using namespace std;class Cat{
private:int age;double weight;string name;string color;
public:Cat(){age = 4;weight = 33.5;name = "mike";color = "red";}//函数重载,构造初始化列表Cat(int a,double b = 25.3,string c = "mike", string d = "red"):age(a),weight(b),name(c),color(d){cout << a << endl;}void printf(){cout << "年龄:" << age << endl;cout << "体重:" << weight <<endl;cout << "名字:" << name << endl;cout << "颜色:" << color << endl;}
};int main()
{//栈内存对象Cat cat1;                                        //不使用参数默认调用无参的构造函数cout << "#################" <<endl;cat1.printf();cout << "#################" <<endl;Cat cat2(8);                    //调用有参的构造函数cat2.printf();cout << "#################" <<endl;//堆内存对象Cat *cat3 = new Cat(1);        //调用有参的构造函数cat3->printf();delete cat3;cout << "#################" <<endl;Cat cat4 = 8;                   //编译器优化,可以把8作为参数传入(隐式调用)cat4.printf();cout << "#################" <<endl;Cat cat5 = {4,44.3,"Lisa","red"};           //隐式调用cat5.printf();//Cat cat6 = "Lisa";              //当第一个参数是字符串类型,就不会优化,对于编译器而言太复杂return 0;
}

补:可以使用explicit屏蔽隐式调用

隐式调用一般用不到,也不好用,使用不安全,容易出现错误

#include <iostream>using namespace std;class Cat{
private:int age;double weight;string name;string color;
public:explicit Cat(){age = 4;weight = 33.5;name = "mike";color = "red";}//函数重载,构造初始化列表explicit Cat(int a,double b = 25.3,string c = "mike", string d = "red"):age(a),weight(b),name(c),color(d){cout << a << endl;}void printf(){cout << "年龄:" << age << endl;cout << "体重:" << weight <<endl;cout << "名字:" << name << endl;cout << "颜色:" << color << endl;}
};int main()
{//栈内存对象Cat cat1;                                        //不使用参数默认调用无参的构造函数cout << "#################" <<endl;cat1.printf();cout << "#################" <<endl;Cat cat2(6);                    //调用有参的构造函数cat2.printf();cout << "#################" <<endl;//堆内存对象Cat *cat3 = new Cat(4);        //调用有参的构造函数cat3->printf();delete cat3;cout << "#################" <<endl;/*            //隐式调用失效Cat cat4 = 8;                     cat4.printf();cout << "#################" <<endl;Cat cat5 = {4,44.3,"Lisa","red"};   //隐式调用cat5.printf();*/return 0;
}

4.拷贝构造函数

拷贝就是复制,创建一个和原对象一样的新对象,被拷贝的对象和拷贝到对象的存储地址是不一样的,不是引用。

在每个类创建的时候,如果程序员不写,都自己会带一个默认的拷贝构造函数(浅拷贝函数)。

    //拷贝构造函数(不写也可以,默认存在)Cat(const Cat &a){age = a.age;name = a.name;}Cat cat1();                //创建第一对象    Cat cat2(cat1);            //拷贝一个对象

1.浅拷贝

如果成员变量出现指针类型,默认的拷贝构造函数会直接拷贝指针变量,多个变量保存在同一个地址,这些对象的成员变量都指向同一块内存,这样的成员变量不符合面向对象的要求,会导致成员变量随着这块空间的内容的变化而变化,还记得我们封装的时候的核心思想是什么?隐藏内部实现细节,成员变量为什么要用private修饰?就是为了防止外部改变,但是拷贝存在指针类型的对象就会出现成员变量随着外部变化而变化的情况。

重写一下代码(写简单点):

#include <iostream>
#include <string.h>
using namespace std;class Cat{
private:int age;char *name;
public://默认的拷贝构造函数(不写也可以)//构造初始化列表explicit Cat(int a,char *b):age(a),name(b){cout << a << endl;}void printf(){cout << "年龄:" << age << endl;cout << "名字:" << name << endl;}
};int main()
{char name[5] = "Lisa";Cat cat1(6,name);                    //调用有参的构造函数cat1.printf();cout << "#################" <<endl;Cat cat2(cat1);                      //拷贝构造函数cat2.printf();cout << "#################" <<endl;strcpy(name,"Join");                   //此时我们改变name内的值cat2.printf();                        //因为构造类我们用的是指针,所以里面的值发生了改变return 0;
}

2.深拷贝

出现上述情况,我们需要修改拷贝构造函数和初始化构造函数,在初始化构造函数的时候,开辟空间,再把内容复制到新开的空间里,这样就避免了成员变量指向外部空间。在C++中使用new开辟空间。

开辟堆空间:

    char *a = new char[10];

优化代码:

#include <iostream>
#include <string.h>
using namespace std;class Cat{
private:int age;char *name;        
public:Cat(const Cat &d){age = d.age;name = new char[5];strcpy(name,d.name);}explicit Cat(){age = 4;name = new char[5];    //开辟空间strcpy(name,"mike");   //复制内容到空间}//函数重载,构造初始化列表explicit Cat(int a,char *b){age = a;name = new char[5];       //开辟空间strcpy(name,b);            //复制内容到空间cout << b << endl;}void printf(){cout << "年龄:" << age << endl;cout << "名字:" << name << endl;}
};int main()
{char name[5] = "Lisa";Cat cat1(6,name);                                        //不使用参数默认调用无参的构造函数cat1.printf();cout << "################" <<endl;Cat cat2(cat1);cat2.printf();cout << "################" <<endl;strcpy(name,"Join");cat2.printf();return 0;
}

四.析构函数

学习上面内容后,还有一个问题,我们使用New开辟的堆空间存在一个问题,这个空间是由程序员开辟和释放的,程序结束才会释放。就像上面代码,我们创造一个栈空间对象,但是内部的name是开的堆空间存放,当对象所在的{}结束,对象cat1就会释放,当时name没有释放,会出现内存泄露。

1.什么是内存泄露?

内存泄露指程序中已动态分配的堆内存由于某种原因未释放无法释放,造成系统内存浪费,导致程序运行速度减慢或崩溃。这类问题在长时间运行的应用中尤为严重。若果不解决,运行过程总会堆积这样的垃圾空间。

2.析构函数

这个时候就可以使用析构函数来解决;析构函数(destructor)是构造函数对立函数也是一种特殊成员函数如果程序员不手写编译器自动添加一个析构函数;析构函数是用来对对象资源的回收,关闭和释放。下面就是析构函数初始版本(不写的默认):

    ~Cat(){}

这也没参数啊,怎么做到的?别管,问就是C++特性,感兴趣可以去看源码。现在我们在析构函数中加上delete name;专门去释放存在堆区域的name变量,就解决了内存泄露的问题。

3.优化代码:

#include <iostream>
#include <string.h>
using namespace std;class Cat{
private:int age;char *name;
public:explicit Cat(){age = 4;name = new char[5];strcpy(name,"mike");}//函数重载,构造初始化列表explicit Cat(int a,char *b){age = a;name = new char[5];strcpy(name,b);cout << b << endl;}//拷贝构造函数Cat(const Cat &a){age = a.age;name = a.name;}void printf(){cout << "年龄:" << age << endl;cout << "名字:" << name << endl;}~Cat(){                             //析构函数,为防止内存泄露cout << "析构函数" << endl;delete name;}
};int main()
{char name[5] = "Lisa";Cat cat1(6,name);                                        //不使用参数默认调用无参的构造函数cat1.printf();cout << "################" <<endl;Cat *cat2 = new Cat;cat2->printf();delete cat2;cout << "################" <<endl;cout << "结束" << endl;return 0;
}

4.析构函数和构造函数比较:

析构函数构造函数

没有参数

可以有参数,支持默认值和重载

函数名称是 ~类名

函数名称是 类名

对象销毁时被调用

创建对象时调用

各种的资源的回收、关闭和释放

数据初始化,各种资源的开辟

五.作用域限定符 ::

概念:

作用域限定符 ::(也称为范围解析运算符)在C++中,是一个关键运算符,用于明确指定标识符(变量、函数、类等)所属的作用域。它的主要功能是消除命名冲突,并提供对特定作用域成员的精确访问。

1.名字空间

名字空间namespaceC++用于解决重名问题设计。在上一篇文章中提到过。

#include <iostream>//using namespace std;//std是C++源码的名字空间
int a = 1;
// 自定义名字空间
namespace my {int a = 3;int b = 4;
}
using namespace my;int main()
{int a = 2;std::cout << a << std::endl; // 2// 匿名名字空间std::cout << ::a << std::endl; // 1std::cout << my::a << std::endl; // 3std::string s = "123";std::cout << b << std::endl; // 4return 0;
}

2.类内声明,类外定义

类内成员(尤指成员函数)可以声明定义分离声明类内定义可以写在类外,这个以后会用的比较频繁。

#include <iostream>using namespace std;class Teacher
{
private:string name;
public:// 只声明Teacher(string n);string get_name();void set_name(string n);
};
// 类外定义
Teacher::Teacher(string n)
{name = n;
}
string Teacher::get_name()
{return name;
}
void Teacher::set_name(string n)
{name = n;
}int main()
{Teacher t1("t1");cout << t1.get_name() << endl;t1.set_name("t2");cout << t1.get_name() << endl;return 0;
}

3.与static关键字配合

在 C++ 中,作用域限定符 :: 与 static 关键字 配合使用主要涉及类的静态成员管理,这是实现类级别数据共享的核心机制。(后面再讲)

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

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

相关文章

驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接,

驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接,Error: “The server selected protocol version TLS10 is not accepted by client preferences [TLS13&#xff0c;TLS12]”. ClientConnectionId:d5fd8d69-ae88-4055-9f6d-6e8515224ce2】。 基本上就是…

【三大前端语言之一】交互:JavaScript详解

【三大前端语言之一】交互&#xff1a;JavaScript详解 在学习完HTML和CSS之后&#xff0c;最后一门前端语言——JavaScript&#xff0c;是重中之重。HTML负责页面结构&#xff0c;CSS负责页面样式&#xff0c;而JavaScript则赋予网页“生命”&#xff0c;让网页可以动起来、响…

LangChain面试内容整理-知识点12:检索器(Retriever)接口与实现

在LangChain中,检索器(Retriever)是一个抽象接口,负责根据用户查询从数据源中检索相关文档。可以把Retriever理解为“搜索工具”:给它一个未经结构化的查询文本(如用户问题),它返回一组与之相关的 Document 对象。内部可以基于向量相似度、数据库查询、甚至网络搜索。 …

LLVM前端和优化层

文章目录 LLVM ArchitectueLLVM 前端Lexical Analysis词法分析Syntactic analysis 语法分析Syntactic Analyze语义分析 LLVM 优化层Pass 基础概念Pass 依赖关系Pass API 总结 LLVM Architectue LLVM 前端 LLVM 的前端其实是把源代码也就是 C、C、Python 这些高级语言变为编译器…

工作流和Agent 的区别与联系

工作流和智能体可能让人混淆的地方就是他们都可能有大模型的加持&#xff0c;都可能有工具的加入供大模型调用&#xff0c;本文做一下对比和联系 工作流 (Workflow) 定义&#xff1a; 工作流是一系列预定义、结构化且可重复的步骤或任务&#xff0c;旨在完成特定的业务目标或解…

leetcode--用StringBulider反转字符串单词的巧妙解法

反转字符串中的单词 这道题理想中的操作方式就是先去除前导和尾随空格&#xff0c;之后设一个尾指针&#xff0c;往前检索&#xff0c;扫到一个单词就把这个单词放到字符串的第一个位置。 很明显&#xff0c;java中我们不能直接对字符串进行修改&#xff0c;而我们想实现一个一…

连锁零售行业智慧能源管理解决方案:精准管控,让每一度电创造价值

在连锁超市、便利店等业态中&#xff0c;门店分布广、用能场景复杂、管理成本高是普遍难题。传统能源管理模式依赖人工抄表与分散管理&#xff0c;存在数据滞后、响应效率低、安全隐患难排查等问题。以某全国几千家门店的连锁便利店为例&#xff0c;其面临的挑战包括&#xff1…

在 PostgreSQL 中实现 `lck`, `special`, `item` 与 `org_id` 或 `user_id` 组合唯一的约束

在 PostgreSQL 中实现 lck, special, item 与 org_id 或 user_id 组合唯一的约束 要实现 lck, special, item 这三个字段必须与 org_id 或 user_id 中的一个&#xff08;但不能同时&#xff09;组合唯一的约束&#xff0c;你需要创建以下约束&#xff1a; 方案1&#xff1a;使…

g++ a.cpp -o a ‘pkg-config --cflags --libs opencv4‘/usr/bin/ld: 找不到 没有那个文件或目录

这个错误表明 pkg-config 命令没有正确执行&#xff0c;导致编译器无法找到 OpenCV 的库文件和头文件路径。pkg-config 是一个工具&#xff0c;用于查询已安装库的编译和链接选项。如果 pkg-config 无法找到 OpenCV 的配置文件&#xff0c;就会导致这个错误。 以下是解决这个问…

定制平板在智能家居中能做些什么?全面解析其核心功能

大家有没有发现&#xff0c;现在智能家居越来越普及了&#xff0c;很多家庭都在逐步升级自己的居住体验。而在这一过程中&#xff0c;一种设备正悄悄地取代我们以前常用的开关面板和手机APP&#xff0c;成为整个家庭智能控制的核心&#xff0c;这就是——定制平板。 它可不是我…

【通俗易懂】Linux 线程调度策略详解

引言&#xff1a;CPU是厨房&#xff0c;调度器是主厨 要真正理解Linux如何处理成千上万个并发任务&#xff0c;不妨把它想象成一个繁忙的专业厨房。这个比喻不仅能让抽象概念变得具体&#xff0c;更能揭示其背后深刻的设计哲学。 厨房 (The Kitchen): 代表整个计算机系统。 厨…

笔记本电脑安装win10哪个版本好_笔记本装win10专业版图文教程

笔记本电脑安装win10哪个版本好&#xff1f;笔记本还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff0c;所…

微服务循环依赖调用引发的血案

问题表现 最近的迭代转测后遇到了一个比较有意思的问题。在测试环境整体运行还算平稳&#xff0c;但是过一段时间之后&#xff0c;就开始有接口超时了&#xff0c;日志中出现非常多的 “java.net.SocketTimeoutException: Read timed out”。试了几次重启大法&#xff0c;每次…

LeetCode - 852. 山脉数组的峰顶索引

题目 852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 思路 使用二分查找来定位峰顶 对于中间元素&#xff0c;比较它与其右侧元素的大小&#xff1a; 如果 arr[mid] < arr[mid1]&#xff0c;说明我们在上坡阶段&#xff0c;峰顶在右侧 如果 arr[mid…

国产ARM/RISCV与OpenHarmony物联网项目(二)网关数据显示

本文需要Web服务器开发基础&#xff0c;可参考下述博文&#xff1a; 物联网网关Web服务器--lighttpd服务器部署与应用测试 物联网网关Web服务器--CGI开发接口 一、数据显示界面与功能设计 1、功能设计说明 程序代码结构如下&#xff0c;调用关系见彩色部分标示。 数据显示界面…

Robyn高性能Web框架系列01:Robyn快速入门

Robyn快速入门 安装 Robyn1、仅安装基础 HTTP 路由功能2、带扩展功能的安装 第一个Robyn程序1、创建Robyn应用2、Say Hello!3、启动Robyn应用 Python世界从来不缺少对于性能的追求&#xff0c;Robyn就是其中之一&#xff0c;它将 Python 的异步功能与 Rust 相结合&#xff0c;在…

微信小程序 -----无限新增删除,同时算出总合算金额。

<view class="refuelMoney-main" style="padding-bottom: 200rpx;"><!-- <view class="add_record">添加加油记录</view> --><view class="refuel-itemTextArea"><text style="width: 35%;&quo…

linux “Permission Denied“解决方案

Linux 编译错误排查 在软件开发过程中&#xff0c;编译错误和版本控制问题是开发者每天都会遇到的挑战。本文将结合实际案例&#xff0c;详细讲解 Linux 环境下常见编译错误的排查方法 权限拒绝错误&#xff08;Permission Denied&#xff09; 当执行脚本或程序时&#xff0…

【慧游鲁博】【15】后台管理系统功能完善:仪表盘、多模态交互日志、简单问答词条管理

文章目录 本次更新多模态交互日志效果涉及代码文件 仪表盘&#xff08;部分&#xff09;效果涉及代码文件 简单问答服务词条管理效果涉及代码文件 本次更新 代码真的太多太多了&#xff0c;不放代码了 多模态交互日志 数据概览与筛选功能 时间范围筛选&#xff1a;提供"…

【力扣 简单 C】21. 合并两个有序链表

目录 题目 解法一&#xff1a;迭代 解法二&#xff1a;递归 题目 解法一&#xff1a;迭代 struct ListNode* merge(struct ListNode* head1, struct ListNode* head2) {struct ListNode* virHead malloc(sizeof(*virHead));struct ListNode* curNode virHead;struct List…