C语言与C++的区别和联系

news2024/11/23 22:36:13

C语言和C++到底是什么关系?

首先C++和C语言本来就是两种不同的编程语言,但C++确实是对C语言的扩充和延伸,并且对C语言提供后向兼容的能力。对于有些人说的“C++完全就包含了C语言”的说法也并没有错。

图片

C++一开始被本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)发明时,起初被称为“C with Classes”,即「带类的C」。

很明显,它是在C语言的基础上扩充了类class等面向对象的特性和机制。但是,后来经过一步步修订和很多次演变,最终才形成了现如今这个支持一系列重大特性的庞大编程语言。

图片

一、C语言是面向过程语言,而C++是面向对象语言

我们都知道,C语言是面向过程语言,而C++是面向对象语言。说C和C++的区别,也就是在比较面向过程和面向对象的区别。

1、面向过程和面向对象的区别

面向过程:面向过程编程就是分析出解决问题的步骤,然后把这些步骤一步一步的实现,使用的时候一个一个的依次调用就可以了。

面向对象:面向对象编程就是把问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

图片

2、面向过程和面向对象的优缺点

面向过程语言:

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展。

面向对象语言:

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

缺点:性能比面向过程低。

图片

二、具体语言上的区别

1、关键字的不同

C语言有32个关键字;C++有63个关键字。

2、后缀名不同

C源文件后缀.c,C++源文件后缀.cpp,在VS中,如果在创建源文件时什么都不给,默认是.cpp。

3、返回值

C语言中,如果一个函数没有指定返回值类型,默认返回int类型;C++中,如果一个函数没有返回值则必须指定为void。

图片

4、参数列表

在C语言中,函数没有指定参数列表时,默认可以接收任意多个参数;但在C++中,因为严格的参数类型检测,没有参数列表的函数,默认为 void,不接收任何参数。

5、缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的参(C语言不支持缺省参数)。

半缺省参数:

图片

全缺省参数:

图片

注意:

(1)在半缺省的情况下,带缺省值的参数必须放在参数列表的最后面。

(2)缺省参数不能同时在函数的声明和函数定义中出现,二者只能选其一。

(3)缺省值必须是常量或者全局变量。

(4)缺省参数必须通过值参或常参传递。

6、函数重载

函数重载:函数重载是函数的一种特殊情况,指在同一作用域中,声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数、类型、顺序)必须不同,返回值类型可以相同也可以不同,常用来处理实现功能类似数据类型不同的问题(C语言没有函数重载,C++支持函数重载)。

图片

C语言中产生函数符号的规则是根据名称产生,这也就注定了c语言不存在函数重载的概念。而C++生成函数符号则考虑了函数名、参数个数、参数类型。需要注意的是函数的返回值并不能作为函数重载的依据,也就是说int sum和double sum这两个函数是不能构成重载的!

我们的函数重载也属于多态的一种,这就是所谓的静多态。

静多态:函数重载,函数模板。

动多态(运行时的多态):继承中的多态(虚函数)。

使用重载的时候需要注意作用域问题:请看如下代码。

图片

我在全局作用域定义了两个函数,它们由于参数类型不同可以构成重载,此时main函数中调用则可以正确的调用到各自的函数。

但是,请看main函数中被注释掉的一句代码。如果将它放出来,则会提出警告:将double类型转换成int类型可能会丢失数据。

这就意味着,我们编译器针对下面两句调用都调用了参数类型int的compare。由此可见,编译器调用函数时优先在局部作用域搜索,若搜索成功则全部按照该函数的标准调用。若未搜索到才在全局作用域进行搜索。

总结:C语言不存在函数重载,C++根据函数名参数个数参数类型判断重载,属于静多态,必须同一作用域下才叫重载。

图片

7、const

C语言中被const修饰的变量不是常量,叫做常变量或者只读变量,这个常变量是无法当作数组下标的。然而在C++中const修饰的变量可以当作数组下标使用,成为了真正的常量,这就是C++对const的扩展。

C语言中的const:被修饰后不能做左值,可以不初始化,但是之后没有机会再初始化。不可以当数组的下标,可以通过指针修改。

简单来说,它和普通变量的区别只是不能做左值而已,其他地方都是一样的。

C++中的const:真正的常量。定义的时候必须初始化,可以用作数组的下标。const在C++中的编译规则是替换(和宏很像),所以它被看作是真正的常量。也可以通过指针修改。需要注意的是,C++的指针有可能退化成C语言的指针。比如以下情况:

图片

这时候的a就只是一个普通的C语言的const常变量了,已经无法当数组的下标了。(引用了一个编译阶段不确定的值)

const在生成符号时,是local符号。即在本文件中才可见。如果非要在别的文件中使用它的话,在文件头部声明:externcosnt int data = 10;这样生成的符号就是global符号。

总结:C中的const叫只读变量,只是无法做左值的变量;C++中的const是真正的常量,但也有可能退化成c语言的常量,默认生成local符号。

图片

8、引用

说到引用,我们第一反应就是想到了他的兄弟:指针。

引用从底层来说和指针就是同一个东西,但是在编译器中它的特性和指针完全不同。

图片

首先,定义一个变量a = 10,然后我们分别定义一个引用b以及一个指针p指向a。我们来转到反汇编看看底层的实现:

图片

可以看到底层实现完全一致,取a的地址放入eax寄存器,再将eax中的值存入引用b/指针p的内存中。至此我们可以说(在底层)引用本质就是一个指针。

了解了底层实现,我们回到编译器。我们看到对a的值的修改,指针p的做法是*p = 20;即进行解引用后替换值。

下面,我们再来看看引用修改。

我们看到修改a的值的方法也是一样的,也是解引用。只是我们在调用的时候有所不同:调用p时需要*p解引用,b则直接使用就可以。由此我们 推断出:引用在直接使用时是指针解引用。p直接使用则是它自己的地址。

这样我们也了解了,我们给引用开辟的这块内存是根本访问不到的。如果直接用就直接解引用了。即使打印&b,输出的也是a的地址。

图片

在此附上将指针转为引用的小技巧:int *p = &a,我们将 引用符号移到左边 将 *替换即可:int &p = a。

接下来,看看如何创建数组的引用:

intarray[10] = {0};//定义一个数组

我们知道,array拿出来使用的话就是数组array的首元素地址。即是int *类型。

那么,&array是什么意思呢?int **类型,用来指向array[0]地址的一个地址吗?不要想当然了,&array是整个数组类型。

那么,要定义一个数组引用,按照上面的小诀窍,先来写写数组指针吧:

int(*q) [10] = &array;

将右侧的&对左边的*进行覆盖:

int(&q)[10] = array;

测试sizeof(q) = 10。我们成功创建了数组引用。

经过上面的详解,我们知道了引用其实就是取地址。那么我们都知道一个立即数是没有地址的,即:

int&b = 10;

这样的代码是无法通过编译的。那如果你就是非要引用一个立即数,其实也不是没有办法:

constint &b = 10;

即将这个立即数用const修饰一下,就可以了。为什么呢?

这时因为被const修饰的都会产生一个临时量来保存这个数据,自然就有地址可取了。

图片

9、malloc,free && new,delete

这个问题很有意思,也是重点需要关注的问题。malloc()和free()是C语言中动态申请内存和释放内存的标准库中的函数。而new和delete是C++运算符、关键字。new和delete底层其实还是调用了malloc和free,它们之间的区别有以下几个方面:

(1)malloc和free是函数,new和delete是运算符。

(2)malloc在分配内存前需要大小,new不需要。

例如:

int *p1 = (int *)malloc(sizeof(int));int *p2 = new int; //int *p3 = new int(10);

malloc时需要指定大小,还需要类型转换。new时不需要指定大小因为它可以从给出的类型判断,并且还可以同时赋初始值。

图片

(3)malloc不安全,需要手动类型转换,new不需要类型转换。

(4)free只释放空间,delete先调用析构函数再释放空间(如果需要)。

与第⑤条对应,如果使用了复杂类型,先析构再call operator delete回收内存。

(5)new是先调用构造函数再申请空间(如果需要)。

与第④条对应,我们在调用new的时候(例如int *p2 = new int;这句代码 ),底层代码的实现是:首先push 4字节(int类型的大小),随后call operator new函数分配了内存。由于我们这句代码并未涉及到复杂类型(如类类型),所以也就没有构造函数的调用。如下是operator new的源代码,也是new实现的重要函数:

图片

我们可以看到,首先malloc(size)申请参数字节大小的内存,如果失败(malloc失败返回0)则进入判断:如果_callnewh(size)也失败的话,抛出bad_alloc异常。

_callnewh()这个函数是在查看new handler是否可用,如果可用会释放一部分内存再返回到malloc处继续申请,如果new handler不可用就会抛出异常。

图片

(6)内存不足(开辟失败)时处理方式不同。

malloc失败返回0,new失败抛出bad_alloc异常。

(7)new和malloc开辟内存的位置不同。

malloc开辟在堆区,new开辟在自由存储区域。

(8)new可以调用malloc(),但malloc不能调用new。

new就是用malloc()实现的,new是C++独有malloc当然无法调用。

10、作用域

C语言中作用域只有两个:局部,全局。C++中则是有:局部作用域,类作用域,名字空间作用域三种。

所谓名字空间就是namespace,我们定义一个名字空间,就是定义一个新作用域。访问时需要以如下方式访问(以std为例):

std::cin<<"123" <<std::endl;

例如,我们有一个名字空间叫Myname,其中有一个变量叫做data。如果我们希望在其他地方使用data的话,需要在文件头声明:using Myname::data;这样一来,data就使用的是Myname中的值了。可是这样每个符号我们都得声明岂不是累死?

图片

我们只要using namespace Myname;就可以将其中所有符号导入了。

这也就是我们经常看到的using namespace std;的意思啦。

不学C语言能直接学C++吗?

还是像前面所说,C++编程语言的第一大重要组成部分就是「面向过程编程」,而这正是C语言老大哥的领域。即使没有学过C语言,一上来就直接学习C++的小伙伴,应该也难逃『面向过程』这一部分的内容。

从理论上来说,学C++前并不一定非得学C语言,但是有C语言底子再去学C++往往更具优势,最起码「面向过程编程」这一部分内容能够轻车熟路。

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

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

相关文章

身份证读取器手持机 二代证核验手持终端 身份证核查手持机

身份证手持机外观比较小巧&#xff0c;方便携带&#xff0c;支持条码识别、人脸识别、NFC卡刷卡、内置二代证加密模块&#xff0c;可离线采集和识别二代身份证&#xff0c;进行身份识别。信息读取更便捷、安全高效。采用IP65高防护等级&#xff0c;1.5M防摔&#xff0c;可以适应…

SmartBear正式收购Stoplight,并计划在核心API设计、文档和门户产品中集成其功能

不久前&#xff0c;软件开发和可视化工具提供商SmartBear正式宣布收购全球领先的API设计公司Stoplight。这一收购是为了打造业内最全面的API开发平台&#xff0c;为寻求现代化API实践的开发团队提供更好的透明度、自动化与生产力。将Stoplight在API方面的优势&#xff08;包括治…

Linux驱动应用层与内核层之间的数据传递

摘要 本文将深入探讨在Linux驱动中&#xff0c;应用层与内核层之间数据传递的机制和优化策略。我们将详细解析这一过程中的各个步骤&#xff0c;包括数据从应用层到内核层的传输&#xff0c;以及从内核层返回应用层的过程。此外&#xff0c;我们将提出并评估一系列可能的优化策…

Docker+K8s基础(重要知识点总结)

目录 一、Docker的核心1&#xff0c;Docker引擎2&#xff0c;Docker基础命令3&#xff0c;单个容器运行多个服务进程4&#xff0c;多个容器运行多个服务进程5&#xff0c;备份在容器中运行的数据库6&#xff0c;在宿主机和容器之间共享数据7&#xff0c;在容器之间共享数据8&am…

已解决:TypeError: ‘NoneType‘ object is not callable 问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

GC5958低压三相无刷直流驱动芯片,无感,正弦,低压,PWM调速可替代APX9358/茂达

GC5958提供了无传感器的三相无刷直流电机的速度控制的所有电路。正弦波驱动器的方法将是更好的低噪声。控制器功能包括启动电路、反电动势换向控制。脉宽调制) 速度控制。锁定保护和热关断电路GC5958既适合游戏机器&#xff0c;也适用于需要无声驱动的CPU冷却器。它以DFN3x3-10…

一篇文章教会你写一个贪吃蛇小游戏(纯C语言)

一篇文章教会你写一个贪吃蛇小游戏 1、游戏展示2、游戏功能3、Win32 API3.1 控制台程序3.2 控制台屏幕上的坐标COORD3.3 GetStdHandle函数3.4 GetConsoleCursorInfo函数3.4.1 CONSOLE_CURSOR_INFO结构体 3.5 SetConsoleCursorInfo函数3.6 SetConsoleCursorPosition函数3.7 GetA…

自动私信引流软件的运行分享,与开发需要到的技术分析

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 一、引言 随着移动互联网的普及和人们对便捷生活的追求&#xff0c;引流APP已成为越来越多企业的必备工具。本文将为大家详细介绍开发引流APP需要用到的技术和流程&#xff0c;帮…

CSS3渐变颜色

CSS3 渐变可以让你在两个或多个指定的颜色之间显示平稳的过渡。 CSS3渐变有两种类型&#xff1a;线性渐变&#xff08;Linear Gradients&#xff09;和径向渐变&#xff08;Radial Gradients&#xff09;。 线性渐变&#xff08;Linear Gradients&#xff09;&#xff1a; 线性…

阻塞队列+定时器+常见的锁策略

1)阻塞队列:是一个线程安全的队列&#xff0c;是可以保证线程安全的 1.1)如果当前队列为空&#xff0c;尝试出队列&#xff0c;进入阻塞状态&#xff0c;一直阻塞到队列里面的元素不为空 1.2)如果当前队列满了&#xff0c;尝试入队列&#xff0c;也会产生阻塞&#xff0c;一直阻…

Ionic 组件 ion-item-divider ion-item-group ion-item-sliding ion-label ion-note

1 ion-item-divider Item dividers是块元素&#xff0c;可用于分隔列表中的items 。它们类似于列表标题&#xff0c;但它们不应该只放在列表的顶部&#xff0c;而应该放在items之间。 <ion-list><ion-item-group><ion-item-divider><ion-label> Secti…

javascript 操作mysql数据库

目录 一&#xff1a;Javascript访问MYSQL 二&#xff1a;JavaScript中操作Mysql数据库实例 一&#xff1a;Javascript访问MYSQL 1、下载MYSQL的ODBC连接 2、在JS中建立ODBC连接如下&#xff1a; var con new ActiveXObject("ADODB.Connection"); con.Connection…

Linux软件包(源码包和二进制包)

Linux下的软件包众多&#xff0c;且几乎都是经 GPL 授权、免费开源&#xff08;无偿公开源代码&#xff09;的。这意味着如果你具备修改软件源代码的能力&#xff0c;只要你愿意&#xff0c;可以随意修改。 GPL&#xff0c;全称 General Public License&#xff0c;中文名称“通…

jbase代码生成器(成型篇)

上一篇说到通用码表可以解决百分之八十的基础维护功能&#xff0c;剩下的百分二十的需要级联维护的界面可以用代码生成器生成代码&#xff0c;基于生成的代码拷贝再组装界面&#xff0c;来解决这百分之二十的工作量里的百分之八十工作量。 首先实现代码生成器 Class Jbase.Ma…

C语言实现给出一位数不大于7位的整型数字,取整数从右端开始的4~7位数字

完整代码&#xff1a; // 给出一位数不大于7位的整型数字&#xff0c;取整数从右端开始的4&#xff5e;7位数字 //就是一个数为abcdefg&#xff0c;取它从右端开始的4&#xff5e;7位数字&#xff0c;就为dcba //如果位数不足7位时&#xff0c;会在数字高位补0 //例如一个数为…

leetcode 62

leetcode 62 题目 解题思路 class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> f(m, vector<int>(n));for(int i0; i<m; i){f[i][0] 1;}for(int j0; j<n; j){f[0][j] 1;}for(int i1; i<m; i){for(int j1; j<n; j){…

如何记录血压的波动情况

import pandas as pd from plotnine import * import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Microsoft YaHei] 记录时间(time)、收缩压(SBP)、舒张压(DBP)&#xff1a; df pd.DataFrame({ time: [2023-11-01 08:30, 2023-11-02 21:00, 2023-11-0…

【星海随笔】SDN neutron (一)

一、SDN的原理&#xff1a; 控制平面与数据平面分离&#xff1a;传统网络中&#xff0c;网络设备同时承担控制和数据转发功能&#xff0c;而SDN将这两个功能分离&#xff0c;使得网络控制集中在一个中心控制器上。 中心控制器&#xff1a;SDN架构中的中心控制器负责网络的全局…

【小黑送书—第五期】>>《MATLAB科学计算从入门到精通》

从代码到函数&#xff0c;从算法到实战&#xff0c;从问题到应用&#xff0c;由浅入深掌握科学计算方法&#xff0c;高效解决实际问题。 从代码到函数&#xff0c;掌握多种经典算法 跨越多个领域&#xff0c;精通各类科学计算 多种应用实例&#xff0c;高效解决实际问题 今天给…

【数据结构】Lambda

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; Lambda表达式 1. 背景1.1 语法1.2 函…