文章目录
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语言的&