Essential C++ 第二章 面向过程的编程风格

2.1 如何编写函数

每个函数必须定义一下四个部分:

1,放回类型

2,函数名

3,参数列表

4,函数体

函数必须先被声明才能调用

2.2 调用函数

两种参数传递方式:传址(by reference) 和传值(by value)

传值:比如我们交换两个数的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;

void mySwap(int a, int b){
int temp = a;
a = b;
b = temp;
}

int main(){
int a = 4, b = 5;
mySwap(a, b);
cout << a << " " << b;
return 0;
}

此时ab的结果为什么呢?很显然a = 4, b = 5,结果并没有改变,因为像我们这样传值进入函数,默认情况下其值会被复制一份,只在函数中有效,和我们主函数中的a,b没有什么联系。

那么我们应该如何修改让ab可以交换呢?答案就是我们传地址进入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;

void mySwap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}

int main(){
int a = 4, b = 5;
mySwap(a, b);
cout << a << " " << b;
return 0;
}

这样结果就为a = 5, b = 4

2.3 提供默认参数值

关于默认参数值的提供,有两个规则:

1,默认值的解析操作由最右边开始进行

1
2
3
4
5
//错误:没有为vec提供默认值
void display(ostream &os = cout, const vector<int>& vec);

//正确
void display(const vector<int>& vec, ostream &os = cout);

2,默认值只能够指定一次,可以在函数声明处,也可以在函数定义处,但不能在两个地方都指定。

通常,函数声明会被放在头文件。

1
2
3
4
5
6
7
#ifndef CIRCLE_H
#define CIRCLE_H

//头文件 NumericSeq.h
void mySwap(int&, int&);

#endif
1
2
3
4
5
6
7
8
//mySwap.cpp
#include "mySwap.h"

void mySwap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//main.cpp

#include <bits/stdc++.h>
#include "mySwap.cpp"
using namespace std;


int main(){
int a = 4, b= 5;
mySwap(a,b);
cout << a << " " << b << endl;
return 0;
}

2.4 使用局部静态对象

局部静态static对象和局部非静态对象不同的是,局部静态对象所处的内存空间,即使在不同的函数调用过程中,依然持续存在,不像局部非静态对象一样,每次在被调用时重新建立,调用完就破坏。

2.5 声明 inline 函数

将函数声明为inline,表示要求编译器在每个函数调用点上,将函数的内容展开。

只要在一个函数前面加上关键字inline,便可将该函数声明为 inline.

一般而言,最适合声明为inline的函数:体积小,经常被调用,所从事的计算并不复杂

2.6 提供重载函数

参数列表不相同(可能是参数类型不同,可能是参数个数不同)的两个或多个函数,可以拥有相同的函数名称

1
2
3
4
void display(char ch);
void display(string&);
void display(int, int);
void display(string& int, int);

2.7 定义并使用模版函数

假设我们增加三个display_message() 函数,分别用来处理 int, double, string 三种vector。

1
2
3
void display_message(const string&, const vector<int>&);
void display_message(const string&, const vector<double>&);
void display_message(const string&, const vector<string>&);

我们希望可以只通过一个函数就可以满足这三种情况,模版函数将参数列表的全部(部分)参数的类型抽离出来。

模版函数以关键字template开场,其后紧接着以尖括号(<>)包围起来的一个或多个标识符。

2.8 函数指针带来更大的弹性

函数指针必须指明其所指的返回类型及参数列表。

2.9 设定头文件

1
2
3
4
5
6
7
#ifndef CIRCLE_H
#define CIRCLE_H

//头文件 NumericSeq.h
void mySwap(int&, int&);

#endif
1
2
3
4
5
6
7
8
//mySwap.cpp
#include "mySwap.h"

void mySwap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}