C++基础一C++基础入门(20000字掌握C++基础知识)
Posted 大家好我叫张同学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++基础一C++基础入门(20000字掌握C++基础知识)相关的知识,希望对你有一定的参考价值。
文章目录
1.C++关键字
C++兼容C绝大多数的语法
C++总计63个关键字,C语言总计32个关键字。
asm | do | if | return | try | continue |
---|---|---|---|---|---|
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explicit | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protected | this | volatile | while |
delete | goto | reinterpret_cast |
以上列出来的关键字不用刻意去记,只需要看一下,在后面的内容中会详细学习到的。
2.命名空间
再学习命名空间之前,我们来看一下以下C++代码,从这样一个小代码入手方便后面的学习。
#include<iostream>//io流,input/output
using namespace std;
int main()
cout << "hello world" << endl;
return 0;
关于上面的这段小代码,有以下几点需要我们注意
1)头文件:
C语言中我们使用头文件是用
#include<stdio.h>//头文件一般是以xx.h结尾的,h表示head(头)
而在C++中,使用头文件一般不再需要.h
#include<iostream>
#include<string>
#include<list>
此外,iostream实际上是input/output stream(输入/输出流)的缩写,一般我们需要使用到和输入输出相关的操作时,就需要包含这个头文件,这点和C语言中的stdio.h(standard input/output,标准输入输出)是一样的。
2)使用了命名空间,将名称为std这个命名空间全部展开了,关于命名空间的内容,后面内容会细讲。
3)使用了关键字cout,读作 see-out,是一个输出控制台,作用类似于printf,但实际又有很大区别,后面也会细讲。
4)流式符号 <<,表示将cout右边的内容流向cout(输出控制台)中,打印出来。
在遇到C语言和C++语法不同的情况下,我们要想弄明白为什么C++要这样设计时,需要知道这样一个原则:
C++每增加一个语法,都是为了解决在C语言中无法做到,或者是C虽然能做到但是很复杂,诸如此类的问题。
下面开始进入我们学习的正题。
2.1 什么是命名空间?
命名空间的关键字是namespace,含义就是这个关键字表面含义,用于管理我们的命名,比如说变量的名称,函数的名称,结构体或类的名称。
2.2 为什么需要命名空间?
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
简单来讲就是为了在名称相同时可以正常使用这些名称,才出现命名空间的。
2.3 如何定义命名空间?
命名空间的定义方式有三种,下面会详细介绍这三种方式。
总原则:定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对花括号即可,花括号内部即为命名空间的成员。
方式一:普通定义
//普通的命名空间
namespace point //point是命名空间的名称
//用花括号 将命名空间的内容括起来
//可以在花括号内部定义变量,函数和结构体
int x;
int y;
int z;
int Add(int x, int y)
return x + y;
struct line
int begin_pos;
int end_pos;
int length;
;
方式二:嵌套定义
//命名空间的嵌套定义
namespace Name1
int a;
int b;
int Add(int x, int y)
return x + y;
namespace Name2
int a;
int b;
int Sub(int x, int y)
return x - y;
方式三:同工程下多次定义
我们可以在同一个工程文件下多次定义命名空间用来扩展命名空间中的成员内容,编译器最后会自动将这些定义在不同地方的命名空间合成到一个命名空间当中的。
比如说下面这个例子:
//同一个工程文件下多次定义,最后由编译器自动合成为一个命名空间
namespace Name1
double c;
double d;
int Add(int x, int y)
return x + y;
namespace Name1
int a;
int b;
void Swap(int* px, int* py)
int temp = *px;
*px = *py;
*py = temp;
虽然我们对命名空间Name1定义了两次,而且每次定义花括号里面的内容都是不同的,但是编译器最终会将这两个定义合成一个,效果和下面这种定义方式是一样的。
//最终编译器合成的效果
namespace Name1
int a;
int b;
double c;
double d;
int Add(int x, int y)
return x + y;
void Swap(int* px, int* py)
int temp = *px;
*px = *py;
*py = temp;
2.4 如何使用命名空间?
定义命名空间是为了方面我们之后对命名空间的使用,其使用的方式也有三种,下面会详细介绍这三种方式。
方式一:全部展开
我们可以使用using namespace
加命名空间的名称,将该命名空间中的内容全部展开,方便我们后面的使用
#include<iostream>
namespace Name1
int a;
int b;
double c;
double d;
int Add(int x, int y)
return x + y;
void Swap(int* px, int* py)
int temp = *px;
*px = *py;
*py = temp;
using namespace Name1;//将自己定义的Name1全部展开
using namespace std;//将C++标准库standard全部展开
int main()
int num1 = 10;
int num2 = 20;
int sum = Add(num1, num2);
cout << sum << endl;
return 0;
优缺点分析
**优点:**全部展开后,我们使用起来会很方便,不用去考虑其命名空间是什么,
比如说我们将标准库 std 展开后,再去使用cout进行输出操作,就不用去考虑它原来在哪个命名空间中。
using namespace std;
**缺点:**可能会出现命名污染。如果我们也定义了一个和全部展开的命名空间中成员名称一样的变量或函数,就会出现命名污染的情况。
总结:日常练习中,我们可以使用全部展开的方式,这样比较方便。但是在工程项目中最好不要全部展开,不然bug满天飞~
方式二:不展开
我们也可以不用展开命名空间,当需要使用到命名空间中的成员时,通过命名空间名称后面跟域作用符来使用
std::cout<<"hello world!";//::就是域作用符
//不展开,通过命名空间名称后面跟域作用符来使用
#include<iostream>
namespace Name1
int a;
int b;
double c;
double d;
int Add(int x, int y)
return x + y;
void Swap(int* px, int* py)
int temp = *px;
*px = *py;
*py = temp;
int main()
int num1 = 10;
int num2 = 20;
int sum = Name1::Add(num1, num2);//::就是域作用符
std::cout << sum << std::endl;
return 0;
优缺点分析:
**优点:**不存在命名污染的问题
**缺点:**用起来很麻烦,每次使用都需要前面加上 命名::(简直烦死了~)
总结:日常练习不推荐这样使用。项目工程中推荐这样使用。
方式三:部分展开
这种方式是全部展开和不展开的一种折中方案,既想保留全部展开时使用的方便性,又想拥有不展开时不存在命名污染的特性。(聪明的小机灵鬼们总会找到解决问题的方法~)
#include<iostream>
namespace Name1
int a;
int b;
double c;
double d;
int Add(int x, int y)
return x + y;
void Swap(int* px, int* py)
int temp = *px;
*px = *py;
*py = temp;
using std::cout;//使用
using Name1::Add;
int main()
int num1 = 10;
int num2 = 20;
int sum = Add(num1, num2);
cout << sum << std::endl;
return 0;
2.5 深入理解命名空间
要想真正弄懂命名空间的含义,我们需要理解作用域和生命周期这两个概念
**作用域:**开始生效到失效的程序范围段
**生命周期:**指的是程序执行过程中该对象存在的一段时间。
两者比较:作用域与生命周期是两个完全不同的概念。 在英文中,作用域用“scope”表示,生命周期则用“duration”表示。 作用域是一个静态概念,只在编译源程序的时候用到。 一个标识符的作用域指在源文件中该标识符能够独立地合法出现的区域。 生命周期则是一个运行时(Runtime)概念,它是指一个变量在整个程序从载入到结束运行的过程中存在的时间周期。 由于函数和数据类型是静态的概念,它们没有生命周期的说法,它们从编译、程序的运行到结束整个过程是一直存在的。
定义了一个命名空间,实际上就是定义了命名空间内部成员的作用域和生命周期,也就是这个成员起作用的范围和和运行时间范围。
3.C++输入&输出
在C语言当中,我们经常会使用scanf( )和prinf( )这两个函数来进行输入输出。因为C++是兼容C语言的,所以C语言当中的绝大多数语法和函数在C++当中仍然可以正常使用。但是C++当中的内容在C语言中不一样能够使用。此外C++作为一门新的语言,自然有其特有的方式来进行输入输出。在此之前我们还需要补充一些容易忽视的知识。
3.1 如何区分C和C++文件
在VS2019中,C源文件是以.c为后缀的,C++源文件是以.cpp为后缀的。
3.2 cin和cout详解
#include<iostream>
using namespace std;//为了后面使用方便,这里直接展开
int main()
int a = 0;
int b = 0;
cin >> a >> b;//从键盘中输入两个整数到a,b中,输入时用空格隔开
cout << "a = " << a << "\\nb = " << b << endl;//将a,b的值输出打印显示出来
return 0;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzy2AzqZ-1647359255281)(https://s2.loli.net/2022/03/10/SfXA1GL9p56B8Nb.png)]
cin >> a >> b;//从键盘中输入两个整数到a,b中,输入时用空格隔开
为了方便理解,我们可以将cin
(读作see-in
)想象成一个输入控制台,>>
是输入运算符/流提取运算符。cin>>a
表示用户通过键盘输入内容放到输入控制台中,然后将输入控制台中的内容提取流向变量a
的存储空间中。
同样,我们也可以将cou
t(读作see-out
)想象成一个输出控制台,<<
是输出运算符/流插入运算符。cout<<a
表示将变量a
存储空间的内容插入到输出控制台中,然后通过输出控制台将内容输出显示打印在屏幕上。
3.3 说明:
1)使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含头文件以及std标准命名空间。
注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名全间,规定C++不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用+std的方式。
2)使用C++输入输出更方便,不需增加数据格式控制,比如:整型–%d,字符–%c
cout << "a = " << a << "\\nb = " << b << endl;//将a,b的值输出打印显示出来
上面这一句输出语句中,我们并没有指定输出格式(比如说用%d输出整数),但仍可以正常输出整数。这就是因为C++中的cout在输出时可以自动检测识别数据的类型。
3.4 建议:
我们在刚开始学C++时,很容易犯迷糊的以一个点就是:“是不是我都在C++了,那么C语言中的内容我就不能再用了,所有东西都要用C++的!”(C语言说:哼,人类可真是喜新厌旧的生物!)
这种想法实际上错的非常离谱,C++虽然是从C语言中发展而来的,但是这并不意味着C++所有的方面都要比C语言好。至少对于我们而言,刚学C++时,C语言比起C++,我们更熟悉。而且C++当中还有很多用起来比较困难,C语言使用比较方便的情况,比如:指定输出数据的格式,double类型指定输出小数点后2位,用C语言可以
double d = 1.22667;
printf("%.2f\\n",d);//C语言当中的这种方式很简单
而在C++当中就非常非常非常麻烦!
#include <iostream>
#include <csdtio>
#include <iomanip>
using namespace std;
int main()
double d = 1.22667;
cout.setf(ios::fixed);//为了防止出现小数点后仅有0,但不显示的情况
cout<<setprecision(2)<<d<<endl;
总结:不管是C还是C++,哪个好用用哪个!
4.缺省参数
4.1 什么是缺省参数?
所谓的缺省参数是指在函数的声明或定义时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。
换一种说法:我们在使用函数的时候,某些参数可以传参,也可以不传参。如果传参了,就会使用传递的参数值;如果不传参数(也就是缺少参数,缺席/缺省),这时候就会使用默认的缺省参数值。
#include<iostream>
using namespace std;
void Print(int x = 10)
cout << x << endl;
int main()
Print();//不传参数,使用缺省参数值10
Print(5);
Print(20);
return 0;
4.2 深入理解缺省参数
理解:缺省参数实际上就相当于我们生活中的备胎,当实际参数不为空的时候,就不使用缺省参数,当实际参数为空的时候才使用缺省参数。类似的道理,汽车的备胎在汽车的主轮胎正常工作的时候就一直搁在后备箱或车尾处,不使用,当主轮胎坏了,不能正常工作时,比如说轮胎爆胎或漏气了,就需要换备胎上路!
以生活中情感的备胎为例的话,如果一个女生和男朋友的关系好好的,那么这个女生的备胎男朋友1号,备胎男朋友2号…3号…都没啥用。当这个女生和男朋友关系闹僵,分手时,备胎1号闪亮登场,迅速成为女生的新任男朋友,备胎2号就变成备胎1号……最后就是
一些奇特的想法:为什么不叫备胎参数?或者舔狗参数呢?
我的想法:可能跟时代的局限性有关系,可能当初提出缺省参数的C++程序员没怎么坐过汽车,然后那个时代也还没有备胎、舔狗这个词,舔狗这个词是互联网新词~
4.3 如何定义缺省参数?
缺省参数是指在函数的声明或定义时为函数的参数指定一个默认值。注意是“或”不是且,也就是说要么在函数声明的时候定义缺省参数,要么在函数定义的时候定义缺省参数,但是不能既在函数声明中定义又在函数定义中定义!
void Print(int x = 10);//在函数声明时定义缺省参数
void Print(int x = 10)//在函数定义时定义缺省参数
cout << x << endl;
上面两种方式均可,但是建议在声明的时候给缺省参数,定义的时候就不要给缺省参数。主要是为了防止声明中和定义中出现的缺省参数值不一样,导致函数执行的时候出现歧义或冲突。
4.4 缺省参数的分类
缺省参数分为两种
第一种:全缺省参数,也就是缺省全部参数,或者说全部参数都是缺省参数。
#include<iostream>
using namespace std;
void Func(int a = 10, int b = 20, int c = 30)
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
int main()
Func();
cout << "----------------------" << endl;
Func(6);
cout << "----------------------" << endl;
Func(6, 8);
cout << "----------------------" << endl;
Func(6, 8, 11);
cout << "----------------------" << endl;
return 0;
注意:全缺省参数只能从左到右依次缺省,不能跳过某个参数值来缺省。
//以下这些方式都是错误的
Func(, 2);//只传第二个,跳过第一个
Func(, , 3);//只传第三个,跳过第一个和第二个
Func(, 2, 3);//传第二个和第三个,跳过第一个
Func(1, , 3);//传第一个和第三个,跳过第二个
代码中的逗号 , 是对传的参数进行分割。假如我们要将3传递给第三个缺省参数
Func(3);//这种方式会默认将参数传给第一个,传不到第三个
Func(,,3);//这种方式才会将参数传给第三个,虽然语法规定了这样的方式是编译不通过的
这个地方不太好理解,因为这是C++语法中规定的,学语法要记忆+理解。我个人的理解方式是:这样规定是为了避免缺省参数出现歧义性,将缺省顺序确定为从左到右依次缺省后,就不会产生传递缺省参数到底是给第一个还是第二个或第三个这个的歧义性问题。
第二种:半缺省参数,不是缺省一半的参数,而是缺省部分参数。也就是一部分参数是缺省参数,另外一部分不是缺省参数。
注意:这个‘半’不是指一半,对半,想想如果有3个参数,难道半缺省参数是1.5个吗?显然这个理解是不对的,这个‘半’的正确理解是相对于‘全’,‘全’是指全部,‘半’则是指部分!
规定:半缺省参数必须从右到左依次来给出,不能间隔着给出
#include<iostream>
using namespace std;
void Func(int a , int b = 20, int c = 30)
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
int main()
Func(1);
cout << "----------------------" << endl;
Func(1, 2);
cout << "----------------------" << endl;
Func(1, 2, 3);
return 0;
对比:缺省的参数只能从右往左连续缺省,调用的时候只能从左往右连续传参(语法规定)
语法的学习需要半记忆半理解,有些东西就是规定死的,没法理解,需要我们直接记忆,有些东西可以理解,理解后有利于强化我们的记忆。(记忆和理解并不是矛盾的,而是相辅相成的)
半缺省参数缺省错误的案例:
Case1:
Case2:
Case3:
半缺省参数缺省正确的案例:
Case1:
Case2:
4.5 缺省参数的注意事项
1)缺省参数不能再函数声明和定义中同时出现(避免声明和定义的缺省值不同而产生冲突)
2)缺省值必须是常量或者全局变量
3)C++支持,而C语言不支持
5.函数重载
引言
在日常生活中,我们可能会经常碰到一个词表示多重含义,一句话可能也能表示多种含义,虽然写法都是一样的。
这个时候,如果我们想要理解这些词和句子表示的真正含义,就需要结合上下文(也就是语境信息)来判断其真正的含义。这些词和句子就被重载了。
有趣的小故事:自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了! ”(谁也/赢不了),后者是"谁也赢不了!”(谁/也赢不了)(中华文化真是博大精深,这里断句也不一定对,小伙伴们可以自己试试)
再比如说初高中学的文言文,经常包含一词多义,比如文言文中的安:①安(怎么)得广厦千万间,大辟天下寒士俱欢颜。②风雨不动安(安稳)如山。③然后生于忧患,死于安(安逸)乐。
此外还有我们学过英语单词,也经常出现同一个单词有多种含义,比如 look 表示 看,寻找,搜索,表情等意思
5.1 什么是函数重载?
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或顺序)必须不同,常用来处理实现功能类似数据类型不同的问题
总结:所谓的函数重载,指的是函数名相同,但是函数的形参个数,类型或类型顺序不同
5.2 函数重载的定义和使用
方式一:形参个数不同
#include<iostream>
int Add(int x, int y)
return x + y;
int Add(int x, int y, int z)
return x + y + z;
以上是关于C++基础一C++基础入门(20000字掌握C++基础知识)的主要内容,如果未能解决你的问题,请参考以下文章
C++基础一C++基础入门(20000字掌握C++基础知识)
C++基础二类和对象(上篇)(10000字掌握C++类核心内容)
C++基础二类和对象(上篇)(10000字掌握C++类核心内容)
C++基础二类和对象(上篇)(10000字掌握C++类核心内容)