文章目录
- 关键字
- 命名空间
- 输入和输出
- 缺省参数
- 函数重载
关键字
相较于C语言32个关键字:
auto | double | int | struct |
break | else | long | switch |
case | enum | register | typedef |
char | extern | return | union |
const | float | short | unsigned |
continue | for | signed | void |
default | goto | sizeof | volatile |
do | if | while | static |
c++的关键字变成了63个:
asm | do | if | return |
try | continue | auto | double |
short | typedef | for | 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 | inline | bool |
显然多一个关键字,多一种可能性。>.<
命名空间
在C语言中,在同一作用域中,同名是不允许的。这就会引发一些问题,例如包含库函数的时候,和定义的全局变量或者函数名冲突。
#include<stdlib.h>
#include<stdio.h>
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
如上所见,我们定义的全局变量和头文件stdlib.h里面的rand函数冲突了,导致程序无法运行。
这样冲突的现象在开发过程中是很容易遇到的,所以C语言这种统一规定所有变量不能重名的设定是不方便的。
由此,c++引入了命名空间的概念:
我们可以用关键字namespace来定义命名空间,
namespace test1
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
namespace test2
{
double rand = 10.;
}
这样我们就能在不同命名空间里面取相同名字rand的变量而不引发报错。
当我们需要使用命名空间时,有以下几种方式:
1.using namespce ;
#include<iostream>
namespace test2
{
double rand = 10.;
}
using namespace std;
using namespace test2;
int main()
{
cout<<rand<<endl;
return 0;
}
using namespace,相当于将命名空间置于全局变量中,里面的所有变量名都可以使用。其中std是c++标准库的命名空间,我们要使用cin、cout等函数时都要使用这个命名空间。
这种方式的缺陷也是很明显的,如果直接把命名空间都解放了,那和c语言又有什么区别呢?
因此还有以下使用方式:
2.使用作用域限定符"::"
#include<iostream>
namespace test2
{
double rand = 10.;
}
using namespace test2;
int main()
{
std::cout<<rand<<endl;
return 0;
}
如上的cout,我们就没有using namespace std,而是用“命名空间::变量名”的形式来使用cout。
需要注意的是当::前为空的时候,默认作用域为全局域。
这种方式能够有效避免了变量名冲突的问题,但同时如果我们这个程序里要多次使用cout这个函数,那每个cout前都要加上std::就显得相当麻烦。因此命名空间的使用还有第三种方式:
3.使用using将命名空间中某个成员引入
#include<iostream>
namespace test2
{
double rand = 10.;
}
using namespace test2;
using std::cout;
int main()
{
cout<<rand<<endl;
return 0;
}
如上我们可以单独拿出std里面的cout函数来使用,这种方式就兼具了上述两种方式的优点,既不会冲突也不会那么麻烦。
当然具体使用哪种方式还是要视情况而定的。不可否认的是,命名空间这个语法的确改善了C语言一大不足之处。
输入和输出
细心的读者已经发现,上面我们使用的输入输出函数不是stdio.h下面的scanf和printf,而是iostream下面的cin和cout。
这也是C和C++不同的地方,特别是当我们使用printf打印数据时,需要使用占位符来格式化数据,而cout则会自动识别数据类型。
使用cout的<<符号称为流插入符,即将数据插入输出流然后输出到屏幕。
那么使用cin的>>符号称为流提取符,从键盘上读取数据到变量中。
缺省参数
在C语言中定义一个函数如:
int Add(int a,int b)
{
return a+b;
}
调用Add函数时,就必须输入两个实参传输过去。
而c++中我们可以使用缺省参数:
int Add(int a=0,int b=0)
{
return a+b;
}
这时当我们不传入实参时,a和b的值就默认为0.这就称为缺省参数。
当然我们可以传入a,b的值也可以只传入a的值,但不能只传入b的值。
关于缺省参数分为以下几类:
- 全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
即函数的参数全为缺省参数。
- 半缺省参数
void Func(int a, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
即有一部分参数为缺省参数。
需要注意的是:
- 半缺省参数必须从右往左依次来给出,不能间隔着给
- 缺省参数不能在函数声明和定义中同时出现(在声明中给出缺少参数,而在定义中不能给缺省参数)
- 缺省值必须是常量或者全局变量(通常为常量)
函数重载
在C语言中,函数重名是绝对不允许的,编译器会报错。而在c++中,允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同。
如:
int Add(int a,int b)
{
return a+b;
}
double Add(double a,double b)
{
return a+b;
}
如上函数定义在c++中是允许的。而在C语言中是不允许的。
这是因为在C语言中,同名函数在编译时给出指向函数的地址都是相同的,因此无法识别同名函数的不同类型。而在c++的编译过程中,会用函数名和参数类型来一定标识函数,由此就能区分开同名函数的不同类型。