C++ - 入门基础概念语法学习

本文详细介绍了C++与C语言的区别,包括C++的命名空间、默认命名空间、输入输出流库、缺省参数、函数重载、引用、auto关键字、范围for语法以及指针空值nullptr的概念和用法。
摘要由CSDN通过智能技术生成

目录

前言

一、C++与C文件的区别与基础语法解释

1.C++的命名空间

2.默认指定命名空间

3.C++官方输入输出流库

1.流插入

2.命名空间内指定展开

3.流提取

二、缺省参数

1.全缺省

2.半缺省

3.注意

三、函数重载

四、函数重载知识点拓展

五、引用

1.引用存在什么意义和价值呢?

1.1传参数意义大

1.2做返回值

2.常引用

3.引用和指针的区别

六、auto关键字

七、范围for语法

八、指针空值nullptr

总结


前言

本章主要是讲解C++中的基础概念与C语言的区别学习。


一、C++与C文件的区别与基础语法解释

创建文件中首先第一区别在于,C语言的文件是使用.c类型,C++文件是.cpp文件类型。
那.c文件是调用C的编译器,.cpp是调用C++的编译器。

又由于C++是由C语言升级而来的,所以C++兼容几乎80%左右的C语言。

1.C++的命名空间

C++中提供了命名空间的概念,由于C语言的缺陷,会产生命名的冲突例如:
1.库中与变量的命名冲突
2.相同库中互相冲突

那提供了命名空间域就能做到名字的隔离,命名空间里可以放变量、函数、结构体等......使用方法 只需要在命名空间的变量前带上 命名空间名 + :: 即可,例如:

这里我们就可以直观的看见,即使是同名rand也可以正常的打印输出。命名空间还可以做到嵌套定义的。

2.默认指定命名空间

        我们为了避免重复 命名冲突的问题,使用了命名空间方案,但使用多了会发现出现了很多累赘,每次使用命名空间里的变量函数都要指定域作用限定符会很麻烦。

指令:using namespace pin;

作用:用于展开命名空间(做工程时不建议展开命名空间,也可能会出现冲突问题)

这里输出的都是main里面的rand了。

如main里没有找到rand的变量,就会在展开的命名空间里去查找是否有rand变量。 

C++提供了std的命名空间是C++官方库定义的命名空间(工程项目不要展开std,容易冲突,日常练习,为了方便就可以展开)

3.C++官方输入输出流库

在C语言里,我们都是导入<stdio.h>库,那C++有没有属于自己的库呢?有的!叫<iostream>库,里面给我们包含了传统的常用库,最重要的是输入输出流,待会解释。在iostream中也有属于他自己的命名空间,就是刚刚说的std。

1.流插入

C++也提供了打印输出,在C语言中是printf函数,C++中提供的是 cout 要配合 << 流插入使用,cout流会自动识别类型,cout 中可以多数据流输出 ,在 C++ 中有个变量endl用于换行。

例子:

从上面的例子可以发现每次都要指定命名空间很不方便,但是刚刚说过直接展开全部变量覆盖可能又会出现冲突的风险,这里提供一种方法。

2.命名空间内指定展开

这种办法是项目中推荐的使用方法

语法:using std::cout;
           using std::endl;

这种方法可以避免命名空间的全覆盖,也保证常用的功能进行使用。

3.流提取

语法:cin

cin相对于C语言中的scanf,但需要配合>>流提取配合使用。也可多个数据输入。

二、缺省参数

函数中的缺省参数是C++对C的优化,在C语言的函数中,我们声明了一个函数里面有形参时,在实参我们就必须要输入数据,但在C++中引入了个缺省参数就可以省略实参的同时在函数中还是有输入数据进形参中,例如:

1.全缺省

语法:void Fun (int a = 10, int b = 20, int c =30);

2.半缺省

语法:void Fun (int a, int b = 20, int c = 30);

3.注意

函数的缺省值要注意的事项:
1.缺省值只能从右往左给,必须是类型的给。参考上面的半缺省,以下例子是错误的:


2.缺省参数不能再函数声明和定义中同时出现,当如果声明和定义位置同时相同,但两个形参给的数值不相同,那么编译器就无法确定该用哪个值,那一般写哪里呢?一般在声明声明时写好缺省参数即可,缺省值必须是常量或全局变量。

三、函数重载

什么是函数重载呢?就是允许多次出现同名的函数,但也有相应的要求:
函数的参数中 1.类型不同 2.个数不同 3.顺序不同 例如:

以上方法都是可行的,但是下面函数重载是不允许的:

函数重载与返回值要求无关,与变量名不相同无关,以上函数是没有区分函数的不同,所以是属于重复的函数,编译器无法区别出来。

四、函数重载知识点拓展

为什么在C++中支持函数重载呢?而C语言中却不支持?

首先我们先理解C++中的文件是如何编译的!!!
现在存在三个文件   Fun.h   Fun.cpp   test.cpp
编译过程:
1.//预处理   头文件展开/宏替换/去掉注释/条件编译.......(最主要部分)
头文件展开:将头文件的内容拷贝到引用的位置
预处理完成后生成  Fun.i    test.i    文件。
(Fun.i里有函数的声明和定义、test.i里有函数的声明和调用)
2.//编译    检查语法,生成汇编代码
汇编代码里都是调用函数,里面存在函数的地址
编译完成生成   Fun.s   test.s     文件。
3.//汇编    将汇编代码转换成二进制的机器码
生成文件   Fun.o    test.o    文件。
4.//链接    将两个文件合并到一起,链接一些没有确定的函数地址等等。
最终生成的文件    a.out

我们知道在C语言中不存在同名的函数,因为C语言链接函数地址的时候,就是用函数名去查找的。
那C++中就不一样了!!!
我们以Linux中为例:
当存在以下同名的函数时

在Linux的函数名修饰规则是:
_Z1Funi、_Z1Fund、_Z2Funid、_Z2Fundi
其实就是以 _Z 函数名字符个数 函数名 参数的首字母 ,所以C++就能实现函数重载了,而C语言就不行,不同的编译器的修饰规则不一样,这只是Linux的修饰规则。

五、引用

简单理解引用就是给一个变量取了一个新的别名,一个对象可以有多个别名,也可以别名继续取别名,最终都还是引用到最开始的变量中。如:

1.引用存在什么意义和价值呢?

1.1传参数意义大

在c语言中我们想使用函数想改名形参影响到实参就必须带上地址才行,那现在有了引用以后形参带上引用就可以直接影响到实参的元素,例:


可能会认为这引用跟*地址传入没什么区别啊?大家可以想想当时写的数据结构单链表中,我们是需要传二级指针才能影响到指针里的数据的,现在有了引用只需要传入变量,就算是指针也能直接进行修改,无需再传入二级指针了,有了引用也可以提高效率,效果与指针相同。
那按照以上的推论,有了引用能不能替代指针呢? 不行!!!
原因:
1.引用必须初始化
2.引用不能改变指向其他的别名,什么意思呢?例:
int a = 1;
int& b = a;
int c = 2;
b = c;(这是一个赋值行为,不是改变指向c)
a = 2,b = 2, c = 2
在Java中引用可以改变指向别名

1.2做返回值

在以往的代码编写下,用引用做返回值,一般情况下会在出了函数作用域,返回的对象会销毁了,不能使用引用返回,否则结果是不确定的。什么意思给个例子就知道了。

其实这里可以在C语言的理解上这里返回了一个变量的地址,当出了函数的作用域时变量就销毁了。
只有函数里是静态变量,动态分配可以使用引用类型返回,拓展一些静态变量,静态局部变量只会初始化一次,后面再调用函数初始化时是不会再执行的。
那引用做返回值有什么用呢?可以直接返回修改的对象,后面学到类时就知道作用了(非常方便)

2.常引用

当我们对一个常数做引用时,按照上面的教程去编写是不允许的,例如:

其实就是一个权限放大的问题,因为变量a是一个常量不允许修改,但引用又可以直接修改变量的数据,这就是妥妥的权限放大的问题,本来人家不给修改的,整个引用又能修改了不就出大问题了?那么我们只能将引用也给const常引用就可以了。

其实这个就是权限的平移,因为大家权限都是一样的。
那有权限放大,权限平移,有没有权限缩小呢?是有的,并且权限缩小是不会报错的。

那可不可以一个整型变量用浮点数类型进行引用呢?这里就要说一下隐式类型转换了。
在进行隐式类型转换时,在转换的过程中,会产生一个临时变量,临时变量是一个常量。

可以发现这里出现了报错了,因为也是权限放大的问题,临时变量是一个const类型,用double类型引用时也是需要用常引用进行修饰,例:

这时候就可以编译成功且正常运行了。

3.引用和指针的区别

首先引用的底层是用汇编去实现的,但在语法上,引用是不占用内存空间的,也就是没开辟空间。
int a = 20;
int& b = a;(语法上,b是没有开空间)
int* ptr = &a;(语法上,ptr是开了空间的,指针占用4个字节)
不过在底层汇编中,都是开了空间的,并且汇编的代码时一样的。

但在实现编写代码中,以现实为准。
引用区别还有很多如:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全
那从上述可以看出,引用对比指针而言会安全一些,但也不是绝对的安全。

六、auto关键字

auto修饰符是一个可以 自动推到类型 的关键字,如:

由以上例子可以看到auto关键字可以自己推导需要的类型,也许可能感觉没什么用,后面我们学习STL时就知道多好用了,我可以举个例子:

可以发现下面两行其实是一个意思的,但是代码上简洁了非常多,是个很好用的关键字。
但又由于代码的简洁性,导致代码的可读性会大幅下降,所以还是需要看情况使用。

七、范围for语法

范围for是c++11引入的一个新语法,有相当强大的功能,我们以前遍历一个数组想打印里面的元素时,需要用 [] 去引用下标查找,现在用范围for就可以了,使用方法:

以上的意思是依次去数组中的数赋值给ch,自动判断结束,自动++往后走,但要修改ch里的数据是不会影响原数组,得用引用auto&即可。

这里可以发现auto和引用的方便与强大了。

八、指针空值nullptr

在C++库中宏NULL为0,但0是int类型,不是指针类型,所以在一些场景上的NULL判断就容易出现问题,所以当以后调用函数传值时,需要传NULL空指针时,使用nullptr来代替。
nullptr宏定义 ((void*) 0)


总结

本章是C++的入门学习,下一章我们就要学习C++中的类和对象,是非常非常难的一章,我将会慢慢给大家讲解,本章如有不足或不正确的地方请谅解也欢迎讨论,如有不懂或不解可以私信一起讨论讨论。

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值