从今天开始就序列更新C++的文章了,希望大家可以耐心的坚持下去学习,有一个很好的成长~~
首先来看一下C++的介绍,百度百科C++ – >点我跳转
C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式
等。熟悉C语言之后,对C++学习有一定的帮助,本章节主要目标:
- 补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的,比如:作用
域方面、IO方面、函数方面、指针方面、宏方面等。- 为后续类和对象学习打基础。
C语言有关键字,那么C++也有关键字,首先我们来认识一下这些关键字
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 |
第二个我们来认识一个新的概念叫命名空间
C++ 的命名空间(Namespace)是一种用于组织和管理代码标识符(变量、函数、类等)的方法。它可以避免命名冲突,使得在不同的命名空间中可以使用相同的标识符而不会产生命名冲突。
使用命名空间可以将一组相关的标识符封装在一起,提供了更好的代码组织和模块化能力。在 C++ 中,可以通过关键字 namespace 定义一个命名空间,并在其中声明相关的标识符。
#include
#include
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
namespace lsl
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
namespace N1
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
那么我这个命名空间域如何使用呢?
来看下面这段代码
namespace lsl
{
// 命名空间中可以定义变量/函数/类型
int a = 0;
int b = 1;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
printf("%d\n", a);
return 0;
}
命名空间的使用有三种方式:
int main()
{
printf("%d\n", lsl::a);
return 0;
}
这里的最后一种方式相信大家学c++或多或少也都见到过,平常在使用c++的时候都要有这么一句using namespace std;,std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中,这里的展开和头文件的展开是不一样的,不要混淆了~~
到这里我们也知道了,首先是先从局部域来搜索,然后从全局域再搜索,搜索不到就报错了,然而我们这里新增加了一个域作用限定符【::】,有了这个就是指定域搜索
不指定域:当前局部域,全局域
指定域:如果指定了,直接去指定域搜索
hello world
,C++怎么来打印呢?#include
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
说明:
<<
是流插入运算符, >>
是流提取运算符。注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持
这里的cout【输出】,cin【输入】可以自动识别类型
std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?
接下来看一个案例就能明白了:
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
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;
}
还有一个重要的点,就是下面这里
我们有人写代码的时候就有可能写成这样的操作,声明的参数和定义的参数不一样,那么是依谁的为准呢?
1. 半缺省参数必须从右往左依次来给出,不能间隔着给
2. 缺省参数不能在函数声明和定义中同时出现
3. 缺省值必须是常量或者全局变量
4. C语言不支持(编译器不支持)
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
函数重载有3个类型,我们分别来看一下:
第二个是参数个数不同
下面我们来看一道题【自己先做一下】来巩固一下:
以下不是double compare(int,int)的重载函数的是( )
A. int compare(double,double)
B. double compare(double,double)
C. double compare(double,int)
D. int compare(int,int)
解析:
A.重载必须是参数列表有所不同(包括个数和类型),所以参数类型不同,构成重载
B.参数类型不同,构成重载
C.参数类型不同,构成重载
D.函数重载不能依靠返回值的不同来构成重载,因为调用时无法根据参数列表确定调用哪个重载函 数,故错误
那么为什么C++支持函数重载呢?而C语言不支持呢?
结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变,之所以就函数名不能相同
结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参
数类型信息添加到修改后的名字中,所以就支持函数重载
对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。
【扩展学习:C/C++函数调用约定和名字修饰规则–有兴趣好奇的同学可以自行搜索看一看,里面有对vs下函数名修饰规则讲解】
通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办
法区分。
最后,本章简单的介绍了C++的关键字,介绍了命名空间的作用和使用,知道了C++的输出和出入,会用缺省参数,以及函数重载~~