文章目录
前言
在之前的文章中,我们学完了初阶数据结构的线性表,栈和队列,堆,二叉树以及排序(详细可以看我之前的几篇文章),在接下来的一段时间内将重点学习c++,c++是在c的基础上,容纳进去了面向对象编程的思想,并且增加了许多有用的库,以及编程范式等。学习c++之前要有一定的C语言基础。本篇文章将讲解c++入门知识,也是对C语言不足的补充,为后序类和对象的学习打好基础。
一.c++关键字
在学习C语言中我们知道关键字之一概念,而在c++中同样也有关键字,甚至数量要比C语言的多,因为c++兼容C语言,所以C语言有的关键字,c++也有。
C语言共有32个关键字,而c++共有64个关键字。如图所示
二.命名空间
在之前c语言中,我们一定遇到过以下这种情况
cpp
#include<stdio.h>
#include<stdlib.h>
int rand = 10;
int main() {
printf("%d", rand);
return 0;
}
上面这种情况就是rand重定义,rand在库函数中是一个函数名,但是在这里我们将它定义为一个变量名,所以产生错误也就是命名冲突 ,而c++为了解决这一问题,引入了命名空间(namespace
)这一概念,而命名空间所在的区域又叫命名空间域。
1.命名空间的定义
定义命名空间,需要使用到
namespace
关键字,后面加命名空间的名字,然后接一对{ },{ }中就是命名空间的成员。命名空间的成员可以是变量,函数或结构体。
cpp
namespace N{
//变量
int rand;
//函数
int Add(int a,int b){
return a+b;
}
//结构体
struct ListNode{
int data;
struct ListNode*next;
};
}
命名空间也可以嵌套使用
cpp
namespace A1{
int a;
int b;
int Add(int left,int right){
return left+right;
}
//命名空间A1嵌套命名空间A2
namespace A2{
int c;
int d;
int Sub(int left,int right){
return left-right;
}
}
}
在同一个工程中允许存在多个同名的命名空间(成员不同),编译器最后都会合成到同一个命名空间中。
比如下面的test.h文件中的命名空间A1和test.cpp文件中的命名空间A1最后会合并成一个。
cpp
//test.h文件中有namespace A1
namespace A1{
int a;
int b;
int Add(int left,int right){
return left+right;
}
}
//test.cpp文件中也有namespace A1
namespace A1{
int c;
int d;
int Sub(int left,int right){
return left-right;
}
}
2.命名空间的使用
在c语言中如果我们直接定义一个变量并初始化,当我们想要打印这个变量的值时,我们可以直接访问
cpp
int main(){
int a=10;
printf("a=%d\n",a);
return 0;
}
//输出结果a=10
而在c++中,当我们将变量定义到命名空间中,再像C语言一样直接访问就会报错
cpp
namespace A{
int a=10;
int b=0;
}
int main(){
printf("a=%d\n",a);
return 0;
}
这时候我们就要使用::
域作用限定符
在C语言中我们知道局部变量所在的为局部域 ,全局变量所在的叫全局域 ,在c++中还有命名空间域 和类域;域影响的是编译时语法查找一个变量或函数或类型出处的逻辑,有了域隔离,就能解决命名冲突。
访问顺序:局部域>全局域>展开命名空间域or指定访问命名空间域
命名空间域展开会暴漏在全局域中,所以不能和全局域同时访问。因此命名空间只能定义在全局中。
当我们要展开命名空间域or指定访问命名空间域时就要用到
::
命名空间的使用方法有三种
-
指定访问某个成员
cppint main(){ //指定访问命名空间A的变量a成员 printf("a=%d\n",A::a); return 0; }
-
使用
using
全部展开命名空间cppusing namespace A; int main(){ printf("a=%d\n",a); printf("b=%d\n",b); return 0; }
-
使用
using
部分展开cpp//注意:这里部分展开不带namespace using A::b; int main(){ printf("a=%d\n",A::a); printf("b=%d\n",b); return 0; }
三.c++输入&输出
在C语言中我们学过输入和输出函数scanf
,printf
,在c++中,同样也有输入输出。在这之前我们先来了解一下什么是std
前面我们学过c++为了解决命名冲突而引入了命名空间,而
std
就是c++标准库命名空间,c++将标准库的定义实现都放在了这个命名空间中,所以在使用c++标准库函数时,我们要展开命名空间或者指定访问。
cpp
//和C语言不同的是,c++的头文件不需要加.h
include<iostream>
using namespace std;
int main(){
//打印输出hello world
cout<<"hello world"<<endl;
//输入x,d的值
cin>>x>>d;
//输出x,d的值
cout<<x<<" "<<d<<endl;
return 0;
}
cout
标准输出对象(控制台,可以理解为vs中的黑框),cin
标准输入对象(键盘),使用时,必须包含头文件,并且正确使用命名空间std
。<<
流插入运算符,<<
流提取运算符。cout
和cin
是全局流对象,endl
是特殊的c++符号,相当于C语言中的'\n'
换行符号。- 相比于C语言中的
scanf
和printf
需要手动控制变量类型,c++的输入输出可以自动识别变量类型,更加方便。
std命名空间的使用惯例:
std是c++标准库的命名空间,如何展开std使用更合理:
- 日常练习中,直接展开
using namespace std
即可。using namespace std
展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对 象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模 大,就很容易出现。所以建议在项目开发中使用,像std::cout
这样使用时指定命名空间 +using std::cout
展开常用的库对象/类型等方式。
四.缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在函数调用时,如果没有指定实参则采用形参的缺省值,否则使用指定实参。
cpp
void Fun(int a=0){
cout<<a<<endl;
}
int main(){
//没有传参数时,使用参数默认值0
Fun();
//传参数时,使用指定的实参1
Fun(1);
return 0;
}
-
全缺省参数
cppusing namespace std; void Fun(int a=0,int b=1,int c=2){ cout<<"a="<<a<<" "; cout<<"b="<<b<<" "; cout<<"c="<<c<<" "; cout<<endl; } int main(){ Fun(); Fun(10); Fun(10,20); Fun(10,20,30); return 0; }
-
半缺省参数
cppusing namespace std; void Fun(int a,int b=10,int c=20){ cout<<"a="<<a<<" "; cout<<"b="<<b<<" "; cout<<"c="<<c<<" "; cout<<endl; } int main(){ Fun(1); Fun(1,2); Fun(1,2,3); return 0; }
注意:
- 半缺省参数必须从右往左依次来给出,不能间隔着给。
- 缺省参数不能在函数声明和定义中同时出现,要在声明中给。
- 缺省参数必须是常量或全局变量
- c++支持缺省参数,C语言不支持
五.函数重载
在我们的日常生活中,我们经常遇到一词多义的情况,也就是多义词,即该词被重载了,在不同的场景下会有不同的含义。而在c++同样也有这一情况,也就是函数重载。
1.函数重载的概念
函数重载是一种特殊的函数情况,c++允许在同一作用域中声明几个功能相似的同名函数,函数的形参列表(参数个数,参数类型以及参数类型的顺序)不同,常用来处理功能类似但数据类型不同的问题。
-
参数个数不同
void f( ){ cout<<"f()"<<endl; } void f(int a){ cout<<"f(int a)"<<endl; }
-
参数类型不同
cppint Add(int a,int b){ return a+b; } int Add(double a,double b){ return a+b; }
-
参数类型的顺序不同
cppvoid f(int a,char b){ cout<<"f(int a,char b)"<<endl; } void f(char a,int b){ cout<<"f(char a,int b)"<<endl; }
-
特殊情况
cppvoid F(){ cout<<"F()"<<endl; } void F(int a=0){ cout<<"F()"<<endl; } int main(){ F(); return 0; } //构成重载 //无参调用时存在歧义,调用不明确
2.编译链接和函数名修饰规则
为什么C语言不支持函数重载,c++支持函数重载,这涉及到编译链接过程 以及函数名修饰规则
编译链接 需要进行以下几个阶段:预处理 ,编译 ,汇编 ,链接。
c++在编译期间链接前会对函数名进行更复杂的修饰,编译器会生成一个包含函数名,返回类型,参数类型等信息的字符串作为修饰名,用于在链接阶段定位函数的正确位置。从而区分同名但参数不同的函数。(注意:不同的编译器函数名修饰格式不一样,以linux系统为例)
cpp//函数名修饰为Addii void Add(int a,int b) //函数名修饰为Adddd void Add(double a,double b)
而C语言的函数名修饰相对简单,通常只是加上一个下划线或者保持不变,所以当出现同名函数时,在链接阶段就会无法正确找到函数位置
以上就是关于c++入门部分的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!