C/C++语言基础--从C到C++的不同(下),15个部分说明C与C++的不同

news2024/11/15 23:56:03

本专栏目的

  • 更新C/C++的基础语法,包括C++的一些新特性

前言

  • 1-10在上篇C/C++语言基础–从C到C++的不同(上);
  • 当然C和C++的不同还有很多,本人暂时只总结这些,其他的慢慢更新;
  • 上一篇C/C++语言基础–从C到C++的不同(上)受到了不少人的喜欢,因此,本人抓紧赶出下篇,欢迎大家点赞 + 收藏 + 关注;
  • C语言后面也会继续更新知识点,如内联汇编;
  • 本人现在正在写一个C语言的图书管理系统,1000多行代码,包含之前所学的所有知识点,包括链表和顺序表等数据结构,请大家耐心等待!!

思维导图如下
在这里插入图片描述

文章目录

    • 11. 枚举类型
      • 1,C语言中的enum
      • 2,C++中的enum
      • 3,C++中的 enum class 强枚举类型
      • 小结
    • 12. auto自动类型推导
    • 13. for循环遍历
    • 14. 类型信息
    • 15. 函数
      • 内联函数
      • 函数默认参数
      • 占位参数
      • 函数重载
        • **函数重载的不同**
        • **重载函数的调用匹配规则**
      • 函数重载遇上默认参数

11. 枚举类型

C语言和C++语言都提供了枚举类型,两者是有一定区别。

有如下定义:

enum SHAPE {CIRCLE,RECT,LINE,POINT};
enum WEEK  {MON,TUE,WED,THI,FIR,SAT,SUN};

1,C语言中的enum

  • 允许非枚举值赋值给枚举类型,允许其他枚举类型的值赋值给另一个枚举类型

    enum WEEK today = 3;	//正确
    today = CIRCLE;			//正确
    
  • 枚举具有外层作用域,容易造成名字冲突(在不同作用域不会冲突,但是遵循就近原则,访问不到外层作用域的枚举)

enum OTHER { RECT };//error C2365: “RECT”: 重定义;以前的定义是“枚举数”
int RECT = 12;		//同上
  • 不同类型的枚举值可以直接比较
if (CIRCLE == MON)
{
	printf("oh.yes");
}

2,C++中的enum

  • 只允许赋值枚举值
enum WEEK today = 3;	//错误	error C2440: “初始化”: 无法从“int”转换为“main::WEEK”
today = CIRCLE;			//错误	error C2440: “=”: 无法从“main::SHAPE”转换为“main::WEEK”
  • 枚举元素会暴露在外部作用域,不同两个枚举类型,若含有相同枚举元素,则会冲突
enum OTHER { RECT };	//错误 	error C2365: “RECT”: 重定义;以前的定义是“枚举数”
int RECT = 12;			//错误同上	但是可以通过枚举名访问指定的枚举属性
OTHER::RECT;			//正确
  • 不同类型的枚举也可以直接比较
if (CIRCLE == MON)
{
	cout<<"oh.yes";
}

3,C++中的 enum class 强枚举类型

enum class SHAPE {CIRCLE,RECT,LINE,POINT};
enum class WEEK  {MON,TUE,WED,THI,FIR,SAT,SUN};
  • 强枚举类型不会将枚举元素暴露在外部作用域,必须通过枚举名去访问
cout<<SHAPCE::RECT<<endl;	//输出 1 
  • 不相关的两个枚举类型不能直接比较,编译报错
if (SHAPE::CIRCLE == WEEK::MON)	//error C2676: 二进制“==”:“main::SHAPE”不定义该运算符或到预定义运算符可接收的类型的转换
{
	cout<<"oh.yes";
}

小结

  • C语言中,枚举可以暴露在外面,且可以枚举与非枚举之间进行比较,赋值等操作;
  • C++中,枚举可以暴露外外面,但是不可以枚举与非枚举之间进行赋值,但是可以比较;
  • C++强枚举中,不可以暴露在外面,必须指明作用域才能使用,枚举与非枚举之间不能进行比较,赋值,就算是枚举与枚举之间,不相关的枚举之间也不行

12. auto自动类型推导

在 C++11 之前的版本中,定义变量或者声明变量之前都必须指明它的类型,比如 int、char 等,这个其实很不方便,尤其是在复杂项目的时候,有多个命名空间,如:Boost::asio::ip::tcp等等,而在其他语言,如js,就只需要用关键字var或者let定义变量就行,到C++11后,auto诞生了,可以在编译的时候制动推导替换类型。

注意:auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。

  • 使用 auto 类型推导的变量必须马上初始化
  • auto 不能在函数的参数中使用(但是能作为函数的返回值)
  • auto 不能作用于类的非静态成员变量(也就是没有 static 关键字修饰的成员变量)中
  • auto 关键字不能定义数组
  • auto 不能作用于模板参数

13. for循环遍历

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误,因此C++大叔给我们提供了一个简单的方法,如下:

int arr[]={1,2,3,4,5,6,7};
//一般用法
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
    cout<<arr[i]<<" ";
}
//新用法
for(int i:arr)
{
     cout<<i<<" ";
}

特点:

  • 从数组的第一个元素开始,逐个赋值给迭代变量;
  • 不依赖于下标元素,通用;
  • 但是,经常还是喜欢用第一种,哈哈哈哈哈哈哈。

14. 类型信息

typeid 是一个运算符,用来获取一个表达式的类型信息。

typeid 的操作对象既可以是表达式,也可以是数据类型,下面是它的两种使用方法:

typeid( dataType )
typeid( expression )

typeid 会把获取到的类型信息保存到一个 type_info 类型的对象里面,并返回该对象的常引用;当需要具体的类型信息时,可以通过成员函数来提取,本质是一个类,封装了大量的API,如下:

//获取一个普通变量的类型信息
int n = 100;
const type_info& nInfo = typeid(n);
cout << nInfo.name() << " | " << nInfo.raw_name() << " | " << nInfo.hash_code() << endl;

//获取一个字面量的类型信息
const type_info& dInfo = typeid(25.65);
cout << dInfo.name() << " | " << dInfo.raw_name() << " | " << dInfo.hash_code() << endl;

//获取一个普通类型的类型信息
const type_info& charInfo = typeid(char);
cout << charInfo.name() << " | " << charInfo.raw_name() << " | " << charInfo.hash_code() << endl;
	
//获取一个表达式的类型信息
const type_info& expInfo = typeid(20 * 45 / 4.5);
cout << expInfo.name() << " | " << expInfo.raw_name() << " | " << expInfo.hash_code() << endl;

其中:

  • name() 用来返回类型的名称。
  • raw_name() 用来返回名字编码(Name Mangling)算法产生的新名称。。
  • hash_code() 用来返回当前类型对应的 hash 值。

除此之外,还可以用 == 比较两个类型是否相等,如下:

char *str;
int a = 2;
int b = 10;
float f;

类型判断结果为:

类型比较结果类型比较结果
typeid(int) == typeid(int)truetypeid(int) == typeid(char)false
typeid(char*) == typeid(char)falsetypeid(str) == typeid(char*)true
typeid(a) == typeid(int)truetypeid(b) == typeid(int)true
typeid(a) == typeid(a)truetypeid(a) == typeid(b)true
typeid(a) == typeid(f)falsetypeid(a/b) == typeid(int)true

建议:内容很多,这个其实也并不常用,可以留个映像,到后面用到的时候查询即可。

15. 函数

内联函数

函数调用时,通过哈希表,需要跳转到函数的地址去执行,执行完成后返回到被调用函数,比较费时,因此,C++中提供了一种操作方式,允许编译时直接把函数替换到调用处,即内联函数

// 使用:
inline int add(int a, int b) {
    return a + b;
}

为什么使用内联函数?
内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)

注意:

  • 内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
  • C++编译器不一定准许函数的内联请求!(只是对编译器的请求,因此编译器可以拒绝)
  • 现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译
    C++中内联函数的限制:
    • 不能存在任何形式的循环语句
    • 不能存在过多的条件判断语句
    • 函数体不能过于庞大
    • 不能对函数进行取址操作
    • 编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。

总结:上面内容过多,很难记住,我也记不住,我只记住了:内联函数可以直接跳转到函数地址中执行,省去入栈出栈等开销,还有就是内联函数之间不能写太多东西

函数默认参数

定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的实参),那么就使用这个默认的值。

void showX(int x = 666)
{
    cout<<"x:"<<x<<endl;
}
showX();
showX(6);

小结:

  • 有函数声明时,默认参数可以放在声明或定义中,但不能同时存在
int add(int a,int b = 5);
int add(int a,int b)
{
    return a+b;
}
  • 注意:函数声明时,必须按照从右向左的顺序,依次给与默认值。
int foo(int a, int b = 2, int c = 3);     // 正确
int foo1(int a, int b = 2, int c);         // 错误, i3未指定默认值
int foo2(int a = 1, int b, int c = 3);     // 错误, i2未指定默认值

占位参数

定义函数时,还可以给函数提供占位参数

  • 占位参数只有参数类型,而没有参数名
  • 在函数体内部无法使用占位参数
  • 占位参数也可以指定默认参数
void func(int a,int = 0)
{
    cout<<a<<endl;
}
func(2);

函数重载

不知道在C语言写函数的时候会不会遇到这种情况,想函数名难想(不想直接拼音),而如果想实现以下功能:

int add(int a, int b) {
    return a + b;
}

int add(double a, double b) {
    return a + b;
}

想实现以上功能的时候,好像名字都可以用add,故在C++的时候,引入了一个新的概念,函数重载。(当然上面的实现还可以更加简介,他可用模板,这个后面会更新)。

函数重载是指:在同一作用域内,可以有一组具有相同函数名不同参数列表的函数,这组函数被称为重载函数。

函数重载的不同
  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同
  • 函数重载与返回值类型无关

来个例子体会一下,比较不同类型的两个变量的大小

int maxmum(int a, int b)
{
	return a > b?a:b;
}
long maxmum(long int a, long int b)
{
	return a > b ? a : b;
}
char maxmum(char a, char b)
{
	return a > b ? a : b;
}
double maxmum(double a, double b)
{
	return a > b ? a : b;
}
const char* maxmum(const char* str1,const char* str2)
{
	return strcmp(str1, str2)==1?str1:str2;
}
char* maxmum(char* str1, char* str2)
{
	return strcmp(str1, str2) == 1 ? str1 : str2;
}

int main()
{
	cout << maxmum(2, 6) << endl;
    cout << maxmum(2L, 6L) << endl;
	cout << maxmum('A', 'C') << endl;

	cout << maxmum("maye", "MAYE") << endl;
	char str1[] = "hello";
	char str2[] = "hello";
	cout << maxmum(str1, str2) << endl;
	return 0;
}

函数重载可以根据具体的参数去决定调用哪一个函数。

重载函数的调用匹配规则
  • 精确匹配:参数匹配而不做转换,或者只是做微不足道的转换,如数组名到指针、函数名到指向函数的指针;
  • 提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double
  • 使用标准转换匹配:如int 到double、double到int、double到long double、Derived到Base、T到void、int到unsigned int;

函数重载遇上默认参数

如果在给重载函数的时候指定默认参数时,这个时候很容易造成函数冲突,如下:

void fun(int a)
{
	cout << "fun(int a) " << a << endl;
}
void fun(int a, int b = 8)
{
	cout << "fun(int,int =8) " << a <<" "<< b << endl;
}
int main()
{
	//fun(5);	//error C2668: “fun”: 对重载函数的调用不明确
	  fun(5, 6);//正确
	return 0;
}

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

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

相关文章

Sass实现文字两侧横线及Sass常用方案

Sass常用方案及Sass实现文字两侧横线 1.Sass实现文字两侧横线2.用Sass简化媒体查询3.使用继承占位符实现样式复用4.Sass 模块化5.lighten 和 darken 自我记录 1.Sass实现文字两侧横线 mixin 的基本作用&#xff1a; 代码复用&#xff1a;把常用的样式封装在一起&#xff0c;…

C++和OpenGL实现3D游戏编程【目录】

欢迎来到zhooyu的专栏。 个人主页&#xff1a;【zhooyu】 文章专栏&#xff1a;【OpenGL实现3D游戏编程】 贝塞尔曲面演示&#xff1a; 贝塞尔曲面演示zhooyu 本专栏内容&#xff1a; 我们从游戏的角度出发&#xff0c;用C去了解一下游戏中的功能都是怎么实现的。这一切还是要…

【刷题日记】螺旋矩阵

54. 螺旋矩阵 这个是一道模拟题&#xff0c;但我记得我大一第一次做这道题的时候真的就是纯按步骤模拟&#xff0c;没有对代码就行优化&#xff0c;导致代码写的很臃肿。 有这么几个地方可以改进。 看题目可以知道最终的结果一定是rows*cols个结点,所以只需要遍历rows*cols次…

Docker部署镜像 发布容器 容器网络互联 前端打包

准备工作 导入相关依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.7</version></dependency><dependency><groupId>com.baomidou<…

CLIP论文中关键信息记录

由于clip论文过长&#xff0c;一直无法完整的阅读该论文&#xff0c;故而抽取论文中的关键信息进行记录。主要记录clip是如何实现的的&#xff08;提出背景、训练数据、设计模式、训练超参数、prompt的作用&#xff09;&#xff0c;clip的能力&#xff08;clip的模型版本、clip…

【Python机器学习】序列到序列建模——对序列到序列模型的增强

有两种增强训练序列到序列模型的方法&#xff0c;可以提高模型的精确率和可扩展性。 使用装桶法降低训练复杂度 输入序列可以有不同的长度&#xff0c;这使短序列的训练数据添加了大量填充词条。过多的填充会使计算成本高昂&#xff0c;特别是当大多数序列都很短&#xff0c;…

你的绩效是不是常年都是B

原创不易&#xff0c;求赞&#xff0c;求关注&#xff0c;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f; 目录 原创不易&#xff0c;求赞&#xff0c;求关注&#xff0c;&#x1f64f;&#x1f64f;&#x1f64…

村落检测系统源码分享

村落检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

Chainlit集成Langchain并使用通义千问AI知识库高级检索(多重查询)网页对话应用教程

前言 之前写过几篇利用Chainlit集成Langchain和国内通义千问大模型集成的知识库检索增加的网页对话应用的技术文章。文章中关于Langchain的知识库检索只是入门级别的教学&#xff0c;本篇文章针对Langchain的知识库高级检索技术和之前对话应用的代码进行完善。 本次主要改进的…

月薪14K的网安公司,来做一下笔试题呀~

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 网络安全简介…

leetcode-枚举算法

1.两数之和 题目一&#xff1a;两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素…

JVM JMM 专题篇 ( 12000 字详解 )

一&#xff1a;JVM 简介 JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java 虚拟机&#xff0c;虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机&#xff1a;JVM、VMwave、Virtual Box&#xff0c;JVM 和其…

微调大模型不再难:LoRA方法带你轻松节省99%的训练成本!

我们之前说大模型有四种玩家&#xff0c;其中前三种都是要做模型训练的。而大部分公司或个人&#xff0c;都是在第二种开源大模型的基础上来做训练。 而这种训练方式又分为两种。一种要么就是从头训练&#xff0c;要么就Fine-tuning接着开源模型来训练&#xff0c;在基座模型已…

IP 协议分析《实验报告》

目录 一、 实验目的 二、实验设备和环境 三、实验记录 1、实验环境搭建 2、IP 协议分析 1.设置抓包接口 2.IP 报文分析 3.报文长度计算 4.生存时间 TTL 5.分析总结 3、IP分片 1.IP 分片简介 2.捕获分组 3.结果分析 一、 实验目的 1、掌握 IP 协议数据报格式&…

知识图谱与异构图神经网络(7)--1

知识图谱是由实体(节点)和关系( 不同类型的边) 组成的多关系图。作为一种非常重要又特殊的图结构数据&#xff0c;知识图谱被广泛应用在人工智能和自然语言处理领域&#xff0c;从语义解析、命名实体消歧到问答系统、推荐系统中都可以看到来自知识图谱的技术推动。本质上&#…

树和二叉树基本术语、性质

目录 树的相关知识 常见考点1&#xff1a;结点数总度数&#xff0b;1 常见考点2&#xff1a; 度为m的树和m叉树 常见考点3&#xff1a;度为m的树第i层至多有结点数 常见考点4&#xff1a;高度为h的m叉树至多有结点 ​编辑 常见考点5&#xff1a;高度为h的m叉树&#xff0c;高…

可靠性:MSTP 和 VRRP 配置实验

一、拓扑&#xff1a; 说明&#xff1a; 1、交换机 SW1、2、3 分别起 vlan 10、20&#xff0c;都以 trunk 方式连接 2、 PC1、2 分别属于 vlan 10、20 3、SW1、2 起 vlan 100 做为管理段&#xff0c;网关地址分别以 100.1.1.1/24 和 200.1.1.2/24 和 AR1相连 …

监控易监测对象及指标之:全面监控InterSystems Cache数据库

随着企业数字化转型的深入&#xff0c;数据库作为核心的信息资产&#xff0c;其性能和稳定性对于保障业务连续性至关重要。InterSystems Cache作为一款高性能、可扩展的数据库管理系统&#xff0c;广泛应用于医疗、金融、制造等行业。为了确保Cache数据库的高效运行和稳定性能&…

Oracle 启动动态采样 自适应执行计划

为了解决因为统计信息缺失或者统计不够准确而引起的问题&#xff0c;从9iR2的版本开始Oracle推出了动态采样&#xff08;Dynamic Sampling&#xff09;功能&#xff0c;使SQL文在硬解析过程中动态地收集统计信息。 该功能在以后的版本上得到更进一步的增强&#xff0c;从11.2.0…

创建一个Java项目并在项目中新建文件,最后实现程序简单的输出

目录 前言 一、建立项目及新建Java类 二、输入简单代码实现输出 前言 1.本文所讲的是java程序设计语言&#xff0c;其内容是如何在id中新建一个项目&#xff0c;并新建一个Java文件&#xff0c;在其内输入相关代码并对其输出&#xff1b; 2.Java文件的编写以收入到我的专栏…