本篇内容要分享的是C++的基础内容,C++的诞生简单的说就是为了填补C语言中的语法坑,同时对比C语言来说增添很多便捷的语法规则,使用起来比C语言便捷不少,但是学习难度也大大增强,不过难度是成线性增长,可以一步一步的深入学习。
目录
1.命名空间
1.1命名空间指定使用
1.2命名空间全部展开
1.3命名空间部分展开
1.4命名空间嵌套
1.5命名空间自动合并
2.关于cout和endl
3.缺省参数
3.1缺省参数简单使用
3.2全缺省参数
3.3半缺省参数
4.函数重载
关于C++的历史本篇不过多分享,有兴趣的可以自行去了解,接下来就直接从代码开始。
首先我们要庆贺的是我们使用VS创建文件时不用再创建.c文件了,可以直接创建.cpp文件
我们都知道.c文件是我们学习C语言所要创建的,而.cpp文件则是C++学习时所要创建的文件,因为C++的语法包含了C语言,所以当时在学C语言时可能不会注意文件的后缀,不过现在既然要学习就要秉着严谨的态度来认识这些细节。
当初我们刚刚接触C语言时敲出的第一段代码就是打印hello world
那现在开始接触C++我们同样的也从打印hello world开始,下面是C++打印hello world
可以看到频幕上就打印出了hello world;
这就是C++入门需要重点学习的地方:命名空间和io流
C++的很多语法规则都是在填C语言所留下的坑,也就是C语言设计上不合理的地方,所以我们不妨对比着C语言来解释以上C++代码的含义;
1.命名空间
如下C语言代码
可以看到这里定义了整形rand,并且可以顺利将其打印出来,但是如果我们做一点手脚
可以看到我们包含了一个stdlib的头文件就不能打印了,这就是C语言的缺陷。
1.1命名空间指定使用
C语言中面临着命名冲突的问题,因为在stdlib这个头文件中同样含有名为rand的函数,在C语言中面对这样的情况我们只能将自己定义的rand改成其他名字, 在工作中如果同组的同事和你用了同样的变量名,那你们只能决定谁来修改命名。
但是在C++更新了一种用法,就是命名空间,用法如下
我们可以使用 namespace+命名 来创建命名空间,将头文件中的全局变量和自己定义的变量隔离起来,这样就不会出现命名冲突的问题,同样的,需要访问命名空间中的数据时,需要如上图使用空间名::来进行访问,否则访问的会是全局变量,所以在C++中有一个新的符号:域作用限定符::
其实可以抽象的将命名空间理解为广场上的一个小房子,需要访问命名空间里的变量、函数或者结构需要使用作用域限定符来访问,就像小房子的钥匙
在简单了解命名空间的使用方法之后再来看看他的其他玩法
namespace wdd
{
int rand = 0;
int Add(int x, int y)
{
return x + y;
}
struct wdd
{
struct Node* next;
int val;
};
}
int main()
{
struct wdd::Node node;
printf("%d \n", wdd::rand);
printf("%d \n", wdd::Add(1,2));
return 0;
}
如上代码所示,其实命名空间内还可以包含很多东西,需要访问命名空间里的数据就需要"钥匙"来进行访问,同时也要注意结构体类型的定义方法。
我们同时在命名空间内同时定义了Add函数
namespace wdd
{
int rand = 0;
int Add(int x, int y)
{
return x + y;
}
}
int Add(int x, int y)
{
return (x + y)*10;
}
int main()
{
printf("%d \n", wdd::rand);
printf("%d \n", wdd::Add(1,2));
printf("%d \n", Add(1, 2));
return 0;
}
可以看到没有通过域作用限定符操作的函数就会调用全局变量的Add函数。
1.2命名空间全部展开
向上面那样使用一次就要通过域作用符操作一次稍嫌麻烦,有没有更加便捷的方法呢?
我们可以直接将作用域展开,情况如下
我们可以直接在命名空间外使用using namespace+空间名即可将对应的空间名全部展开。
这样的操作就意味着将广场上的小房子拆除掉,小房子中所有的资源都会成为公有,所以展开命名空间的操作很危险。
展开命名空间之后可以看到rand已经出现错误了,因为不知道调用的是头文件中的rand还是命名空间中的rand。
1.3命名空间部分展开
还有一种是用环境就是我们想要多次的调用命名空间里的函数或者变量,那还有一种方法如下
在使用的时候指定展开命名空间里的函数或其他数据,就可以直接调用里面的函数,我们称之为部分展开。
1.4命名空间嵌套
命名空间同样也可以嵌套使用如下代码
namespace wdd
{
int rand = 0;
int Add(int x, int y)
{
return x + y;
}
struct wdd
{
struct Node* next;
int val;
};
namespace zmj
{
int rand = 1;
}
}
int main()
{
printf("%d \n", wdd::zmj::rand);
}
运行结果如图
这就是命名空间嵌套使用。
那我们再回过头来看用C++打印hello world的那段代码
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
很明显using namespace std就是展开std这个命名空间,std是C++标准库的命名空间,为了防止和自己定义的变量名称产生冲突。
那同样的只有展开了std才能使用cout,我们也可以采用如下几种方法使用cout
1.部分展开
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout << "hello world " << endl;
return 0;
}
2.指定展开
#include<iostream>
int main()
{
std::cout << "hello world " << std::endl;
return 0;
}
通过以上学习我们就可以使用这几种方法来展开std打印hello world。
1.5命名空间自动合并
如果我们定义了同名的命名空间,编译器就会自动将同名的命名空间合并,如下列
可以看到在两个不同的头文件里定义了相同名的命名空间,也就是说多个命名相同的命名空间并不会冲突。
2.关于cout和endl
因为cout和endl详细实现是有关于类和对象的,所以这里简单介绍一下他们的使用即可;
在cout和endl中,cout 的c是console的意思,也就是控制台的意思,那么cout就是在控制台输出的意思,也就是打印出来的黑框。endl就是换行的意思,和\n的用处相同
cout << "hello world" << endl;
而<<符号是流插入输入符,那上面代码的意思很形象的就是hello world流向cout输出;
那同样,有插入就有提取,>>就被称为流提取通常与cin使用
int i=0;
std::cin>>i;
这里的意思就是输入i。
这里重要的是cout和cin可以自动识别类型,这是printf和scanf做不到的;
#include<iostream>
using namespace std;
int main()
{
int i = 0;
double j = 0;
cin >> i >> j;
cout << i << endl;
cout << j << endl;
return 0;
}
可以看到测试出来i和j是可以自动识别类型的
3.缺省参数
3.1缺省参数简单使用
直接上代码讲解语法规则
#include<iostream>
using namespace std;
void Func(int a = 1)
{
cout << a << endl;
}
int main()
{
Func(2);
Func();
}
缺省参数就是以在定义函数参数的时候加上缺省值,如上代码可以看到在定义函数时在参数中定义了整形并赋值;
当我们在main函数中使用时可以传参,也可以不用传参;以下是运行结果
可以看到当我们调用函数时,如果我们传进去参数,函数就会使用我们传进去的参数;如果不传参,那函数就会使用缺省参数。
3.2全缺省参数
定义缺省参数还可以定义多个,玩法多样
#include<iostream>
using namespace std;
void Func(int a = 1, int b = 2,int c=3)
{
cout << a << ' ' ;
cout << b <<' ';
cout << c << endl;
}
int main()
{
Func();
Func(10);
Func(10,20);
Func(10,20,30);
}
运行结果如下
但是需要注意的是,不能间隔传参
这样传参并不会 只调用第二个参数,这样传参是不符合规矩的。
3.3半缺省参数
和全缺省类似,半缺省就是定义函数时部分赋值
void Func(int a , int b = 2, int c = 3)
{
cout << a << ' ';
cout << b << ' ';
cout << c << endl;
}
半缺省参数只能是从右向左给缺省值,并且没有在函数里给缺省值的要在调用函数时传参
否则就会报错。
还需要注意的是缺省参数不能定义和声明分离,下面用代码示例
首先我们在.cpp文件中 定义出缺省参数
我们再在头文件中添加声明
继续在mian函数中测试
可以看到报错了,原因很简单:当编译器调用函数的时候无法确定调用的是,h文件中声明里的缺省值还是.cpp文件中的缺省值,如果声明和定义的函数缺省值不相同就会出现冲突,
可以看声明和定义分离会出现以上这种情况
所以不允许声明和定义同时给缺省参数。
4.函数重载
首先我们要知道重载是什么意思,在我们学习语言方面重载就是一词多义的意思,之前有个段子说中国有两项运动根本不用看,一个是乒乓球,一个是足球;乒乓球谁也打不过,足球谁也打不过,这句话就构成重载;
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
同样的,C语言中不支持同名的函数,C++却可以,但是要求构成重载(函数名相同,参数不同)。
直接上代码解释
#include<iostream>
#include"Stack.h"
using namespace std;
int Add(int x, int y)
{
cout << "int Add(int x, int y)" << endl;
return x + y;
}
double Add(double x, double y)
{
cout << "double Add(double x, double y)" << endl;
return x + y;
}
int main()
{
cout << Add(1, 2) << endl;
cout << Add(1.1, 2.2) << endl;
}
以下是运行结果
可以看到在C++中可以自动识别类型,比C语言方便太多.
除了以上的参数类型不同,还有以下几种情况也可以构成重载
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
但是要注意的是返回值不同,是不能构成重载的
还有一种情况是在不同作用域的函数,情况如下
同样的这样也是不能构成该函数重载的,因为他们的作用域不同,在概念的解释中作用域不同不能够成函数重载。
以上就是本片要分享的内容,后序还有更多C++学习的内容,如果对你有帮助还请三连支持,感谢阅读。