目录
一.🚀前言🚀
在之前的博客中,博主讲解了C语言,并且前面讲解的数据结构也是用C语言实现的,看过博主前面的博客的小伙伴肯定会发现用C语言来实现种种数据结构时,往往需要很长的代码,但是实现相同的数据结构,C语言可能要200行代码,而C++可能只需要80行,在实际的编程中,C++的运用也远高于C语言。那么,今天我们就来看看C++到底是什么?
二.🚀初识C++🚀
1.✈️什么是C++?✈️
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的
程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机
界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言
应运而生。
1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一
种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而
产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的
程序设计,还可以进行面向对象的程序设计。
2.✈️关键字✈️
C++总计63个关键字,C语言32个关键字,C++是兼容C语言的,因此C语言中的那些语法以及关键字在C++中同样适用。
3.✈️命名空间✈️
(1)🚁命名空间的作用和出现的原因🚁
相信各位小伙伴,大多数第一次接触的程序都是“Hello world”,下面我们用C语言以及C++ 分别实现一下Hello world。
//C语言版hello world
#include<stdio.h>
int main()
{
printf("hellod world");
return 0;
}
#include<iostream>
//using namespace std;//namespace是命名空间 -- 命名空间域,只影响使用,不影响生命周期
int main()
{
//cout << "hello world" << endl;// <<是流插入符号,也叫流向;endl是换行
std::cout << "hello world" << std::endl;//:: 域作用限定符
return 0;
}
<iostream>是输入输出流,是std的头文件,而std是标准库名字空间,说到名字空间就不得不说一下关键字---namespace,namespace关键字用于命名空间域,std就是一个空间域,cout是输出,endl是换行,而域又是什么呢?先来看下面这个代码:
#include<stdio.h>
int a = 2;
void Fun1()
{
int a = 0;
printf("%d\n", a);//打印局部变量a
printf("%d\n", ::a);//打印全局变量a,::是域作用限定符,当其左边为空时,它就会到
//全局域中去寻找变量a
}
int main()
{
Fun1();
return 0;
}
我们知道初值为2的a为全局变量,另一个a为局部变量,打印时根据局部优先的原则,将打印局部的a的值,再来看,局部变量a的生命周期就在函数Fun1的范围内,而这个范围就是一个域,一个局部域,且是局部变量a的作用域。而全局变量a在整个程序内任意地方都有效,其生命周期为整个程序,整个程序这个范围同样是一个域,一个全局域,也即是全局变量a的作用域。通过上述分析你会发现,全局域和局部域会有两个影响:1.影响变量的使用,例如局部变量出了局部域就不能够使用。2.影响生命周期。
假如想要在Fun1中打印全局变量a,则可以使用域作用限定符(::),域作用限定符的左边是域名,右边是要寻找的变量,当其左边为空时,其域就是全局域,所以上述代码中 ::a的意思就是在全局域中寻找a。换句话说,域作用限定符将a的寻找范围限定到了全局域中。
说了这么多,那么namespace到底有什么作用呢?再来看下面这个代码:
#include<stdio.h>
int sum(int x, int y)
{
return x + y;
}
int main()
{
int sum = 10;
int ret = sum(2, 3);
printf("%d\n", ret);
return 0;
}
首先说明一点,这是一个错误代码,因为在C语言中,上述代码中变量sum与函数名sum重名了,这正是C语言的一个缺陷,一旦重名,无论它是变量还是函数,都无法编译通过。有的小伙伴可定会这么说:“这有什么,我换个名字不就行了吗”,那么假如下面这种情形呢,现在让你写两个函数,分别计算double类型数据的两数之和以及整形数据的两数之和,你会怎么写呢?小伙伴们可以试着写写看。代码如下:
#include<stdio.h>
int sum(int x, int y)
{
return x + y;
}
double sum(double x, double y)
{
return x + y;
}
int main()
{
int ret = sum(2, 3);
printf("%d\n", ret);
return 0;
}
在C语言下,这个代码同样编译不过,原因是两个sum重命名了,编译器不知道到底该调用哪一个sum函数,除此之外还有一个状况就是在公司实际编写项目时,一个项目同时由多个人完成,其中就难免会使用相同的变量名或是函数名,而当把所有模块汇总到一起时,肯定就会出现重命名的情况,导致无法编译通过,这也是C语言一个致命的缺陷。而namespace的出现就是为了解决这一问题。
上面我们说过,namespace的作用就是命名空间域,那它怎么用呢?看代码:
#include<stdio.h>
namespace A
{
int sum(int x, int y)
{
return x + y;
}
}
namespace B
{
double sum(double x, double y)
{
return x + y;
}
}
int main()
{
int ret1 = A :: sum(2, 3);
double ret2 = B::sum(1.23, 3.24);
printf("%d\n", ret1);
printf("%lf\n", ret2);
return 0;
}
将整形求和函数单独立于空间域A中,将双精度浮点型求和函数单独立于空间域B中,访问sum函数时,用域作用限定符进行域限定就能够找到对应的函数。其中A,B就是namespace定义的空间域域名。(为了方便理解,上面这个代码是博主将C++与C语言混合着编写的,C++兼容C)
(2)🚁命名空间的三种使用🚁
1)指定命名空间访问---如std::cout(实际编程中通常都是用指定命名空间访问)
2)全部展开---如using namespace std;(一般情况,不建议全局展开)
全局展开其实就是将std暴露于全局域下,这样就不用每次访问都加域名,例如上面用C++实现的Hello world中就有写指定命名空间访问和全部展开。
3) 部分展开---如using std::cout;using std::endl;
4.✈️自动识别类型✈️
先来看一个代码:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
cin >> a;
cout << a << endl;
double b = 3.14;
cin >> b;
cout << b << endl;
return 0;
}
执行结果:
cin是流提取,简单来说就是输入,可以发现,在C++中,无论是用输入还是输出都没有指定类型,但是输入输出却都是正确的,而在C语言中,无论是输入还是输出都需要指明输入输出的具体类型,例如scanf("%d",&a);printf("%lf\n",b);所以C++具有自动识别类型的功能。因此,上面求和的那个地方,还可以这样写:
#include<iostream>
using namespace std;
namespace A
{
int sum(int x, int y)
{
return x + y;
}
}
namespace B
{
double sum(double x, double y)
{
return x + y;
}
}
int main()
{
cout << A::sum(2, 3) << endl;
cout << B::sum(1.23, 3.24) << endl;
return 0;
}
cout会自动识别类型并打印,cin同样也会自动识别键盘输入的类型。
5.✈️缺省参数✈️
(1).🚁缺省参数的概念🚁
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
什么是缺省值呢?看下面这个代码:
#include<iostream>
void fun(int i = 0)
{
std::cout << i << std::endl;
}
int main()
{
fun();
fun(1);
return 0;
}
上面代码中与我们在C语言中写的代码有个很明显的区别,那就是形参给了值,这个给了值的形参就叫做缺省参数,这个值就叫做缺省值。上面说过,在调用带有缺省参数的函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,这是什么意思呢?例如上述代码中,第一次调用fun()函数时,没有给传实参,这就是没有指定实参,所以此时的i等于0;第二次调用fun()函数时,传了实参,值为1,这就是指定了实参,因此,此时i等于1,所以最后打印出的结果应是0,1。
执行结果如下:
需要说明的是,缺省参数并不是只能有一个,而是可以为对个,这取决于你要写的函数需要传多少个参数,而你又需要设置几个缺省参数。
(2).🚁缺省参数的分类🚁
1).🛩️全缺省参数🛩️
//全缺省参数
#include<iostream>
using namespace std;
void fun1(int a = 10, int b = 20, int c = 30)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
cout << endl;
}
int main()
{
fun1();
fun1(1, 2);
fun1(1, 2, 3);
return 0;
}
全缺省参数,顾名思义,参数全部都是缺省参数。fun1()一个实参都没给,所以a,b,c都等于缺省值,因此打印出10,20,30;fun1(1,2)给a,b传了实参,c没传,因此打印出1,2,30;fun1(1,2,3)给a,b,c都传了实参,即指定了实参,因此打印出1,2,3;
注意:传实参时是不能够跳着传的,如这样:fun1(1, ,3);
2).🛩️半缺省参数🛩️
//半缺省参数
#include<iostream>
using namespace std;
void fun1(int a, int b = 20, int c = 30)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
cout << endl;
}
int main()
{
fun1(1);
fun1(100, 200);
fun1(100, 200, 300);
return 0;
}
半缺省参数不是说刚好有一半参数是缺省参数,而是指除去全缺省参数之外的所有缺省参数的情况都叫做半缺省参数。
注意:1.半缺省参数的函数中,非缺省参数必须传实参,只有缺省参数才可以选择不传。
2.半缺省参数必须从右往左依次来给出,不能间隔着给。
fun1(int a = 10,int b,int c = 30);--->错误的缺省参数给法
3.缺省参数不能在函数声明和定义中同时出现。
(3).🚁缺省参数的运用🚁
栈是一种数据结构,关于栈的讲解博主之前有发过一篇博客,可到博主主页查找,也可点击下方链接进行学习,链接:http://t.csdnimg.cn/PXLxu
假如现在我们需要用栈来存放两种情况下的数据,情况一是确切的知道需要在栈中存放100个数据,情况二是不知道要存放多少个数据,用栈来存放数据,那势必要开辟空间,若将两种情况取中,都开辟存放100个数据的空间,若情况二只存放3个数据,那就必定会造成空间的浪费,而若空间开小了,那情况一又存不下,面对这种情况,缺省参数就排上了大用。我们可以将初始化函数的第二个参数设置为缺省参数,并将缺省值设置为4(其他值也行,但是尽量写一个较小的值,一免空间开大了造成浪费)。面对情况一,我们可以直接传一个实参100过去进行初始化,那么第一种情况下的100个数据的空间就开好了;面对第二种情况,第二个参数不传实参,直接使用缺省值开辟存放4个数据的空间,若不够再进行扩容。(开辟空间之前其实应该先进行判断栈空间是否已满,下面这个代码仅仅用于说明上述的情况,没有写完整)。
#include<iostream>
struct Stack
{
int* a;
int top;
int capacity;
};
void StackInit(struct Stack* pst, int defaultcapacity = 4)
{
int* tmp = (int*)malloc(sizeof(int) * defaultcapacity);
if (tmp == NULL)
{
perror("malloc fail");
return;
}
pst->a = tmp;
pst->capacity = defaultcapacity;
pst->top = 0;
}
int main()
{
struct Stack st1;
StackInit(&st1, 100);//最多准备存放100个数据
struct Stack st2;
StackInit(&st2);//不知道存放多少个数据
//缺省值刚好可以同时解决上述的两种情况
return 0;
}
本篇以初试C++为主题的博客到此就要结束了,希望本篇博客可以帮助到各位小伙伴,博主码字不易,如果本篇博客对你有所帮助,还望各位小伙伴点赞👍,收藏⭐+关注,感谢各位的支持!如果有什么不明白的地方或是另有其他的高见,也可以在评论区留言,博主也会及时回复或进行更改,欢迎指正,谢谢!