[toc]
记录一些容易忘记的C++知识
C++知识体系较为庞杂,学得不够系统,对知识点进行记录和定期复盘是很有必要的。现在想重新过一遍《C++ Primer Plus》,把一些被遗忘了的和还未学习的知识记录下来,方便日后查阅。
正篇开始
1. 头文件
C语言的头文件使用扩展名.h
,C++则没有扩展名,但仍然可以使用C语言的.h
文件。有些C头文件被转换为C++头文件,并被重新命名,去掉了扩展名.h
,并在文件名称前面加上前缀c,例如,C++版本的math.h
为cmath
。没有.h
扩展名的头文件可以包含名称空间。
2. 函数
C/C++不允许将函数定义嵌套在另一个函数定义中;
在C++中,不指定参数列表时应使用省略号
void func(...){ }
,通常,仅当与接受可变参数的C函数交互时才需要这样做;C++函数不能直接返回数组,但可以将数组作为结构或对象的组成部分来返回;
函数返回对象时,有可能使得下面的代码能够通过编译:
1
2
3
4
5
6
7
8
9
10
11
12Vector v1, v2;
Vector v3;
// 重载加法运算符
Vector Vector::operator+(const Vector & rv)
{
return Vector(x + rv.x, y + rv.y);
}
v3 = v1 + v2; // 正常使用逻辑
v1 + v2 = v3; // 能够通过编译,先执行operator+,再执行operator=为防止在使用赋值运算符的时候出错,可以把返回值设置为
const
类型。传递数组:
1
2
3
4
5
6int sum(int [], int); // 函数原型
int sum(int *, int); // 另一种形式
int sum(int array[], int n){return 0;} // 函数定义,sizeof array将等于指针类型长度
/*为防止函数无意中修改数组的内容,可在声明形参时使用关键字const*/
int sum(const int *, int); // 这表明该形参指针指向的是常量数据,不允许通过该指针进行修改函数不能返回字符串,但是可以在函数体中申请内存空间,返回该内存空间的地址,以此来返回一个字符串;
函数的地址:
函数的地址是存储其机器语言代码的内存的开始地址。==函数名==就是函数的地址。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 声明函数指针
double (*pf)(int); // 可以首先编写函数的原型,然后用(*pf)替换函数名
// 通过函数指针调用函数
double y = (*pf)(x);
double y = pf(x); // C++中也允许像使用函数名那样使用pf
/*声明函数指针数组,运算符[]的优先级高于*,所以pf[3]表明其是一个包含三个元素的数组,*pf[3]表明其是一个包含三个指针的数组,其他部分的内容则说明这些指针是函数指针。此处不能使用auto关键字,因为自动类型推断只能用于单值初始化,不能用于初始化列表。但是声明数组pf后,可以使用auto来声明同类型的数组
*/
const double * (*pf[3])(const double *, int) = {f1, f2, f3};
auto pa = pf;
pf[0](cpd, 3); // 通过函数指针数组和索引调用函数
const double * (*(*pd)[3])(const double *, int) = &pf; // 指向函数指针数组的指针,我的天呐
/*使用typedef进行简化*/
typedef const double * (*p_fun)(const double *, int);
p_fun p1 = f1; // 声明函数指针变量,p_fun为新类型的别名
p_fun p2[3] = {f1, f2, f3}; // 创建函数指针数组,很方便
p_fun (*pd)[3] = &f1; // 创建指向函数指针数组的指针