第2章 面向过程的编程风格
2.1 如何编写函数
函数定义:
每一个函数必须定义以下四个部分:
1.返回类型。
2.函数名
3.参数列表
4.函数体
函数必须先声明,然后才能被调用。函数声明让编译器能检查函数的使用是否正确。
函数声明:
函数声明需要包含返回类型、函数名、参数列表,也称为函数原型。
2.2 调用函数
两种参数传递方式:传地址、传值
当我们调用一个函数时,会在内存中建立一块特殊区域,称为程序堆栈。一旦函数完成,这块内存会被释放,里面的临时对象也会消失。
通过传地址,可以将函数参数和实际对象产生关联。
void swap(int &val1.int & val2)
作用域和地址:
对象如果在函数以外声明,具有file scope,从声明点到文件末尾都可见,file scope内的对象具有static extent,从main()开始执行前内存就已经分配好了,一直持续到程序结束。
动态内存管理
分配动态内存使用new
释放动态内存使用delete
例子:
int *pi = new int;
int *pi = new int(10);
int*pia = new int[24]; //分配数组
delete pi; //删除pi所指的int
delete [] pia;//删除数组
2.3 提供默认参数值
C++允许我们为函数参数提供默认值
关于默认参数有两个规则:
1.默认值的解析是从右开始的,如果我们为某个参数提供默认值,那么它右面的参数也要有默认值。
2.默认值只能指定一次,可以在函数声明处,也可以在函数定义处。
通常放在声明处。
例子:
//NumericSqe.h
void display(const vector<int>&, ostream&=cout);
#include”NumericSeq.h”
void display(const vector<int>& vec, ostream &os)
{
…
}
2.4 使用局部静态对象
使用 局部静态对象:
const vector<int>*
fibon_seq(int size)
{
static vector<int> elems;
…
return &elems;
}
elems被定义为函数中的局部静态对象。局部静态对象所处的内存空间。即使在不同的函数调用过程中,依然持续存在。
2.5 声明inline函数
将函数声明为inlien函数,表示要求编译器在函数调用点将函数内容展开。
只要在函数前加上关键字 inline就可以将函数声明为inline:
inline函数的定义一般在头文件中。
比较短小的函数适合定义成inline函数。
2.6提供重载函数
参数列表不相同(参数类型或参数个数不同)的函数可以拥有相同的函数名称。
如:
void display(char ch);
void display(const string&);
调用时编译器通过参数列表知道该调用哪个函数。
2.7 定义并使用模板函数
函数模拟(function template)通过了一种机制,让我们得以将单一函数的内容与各种类型绑定(bind)起来。
function template将参数列表的部分参数的类型抽离出来。
function template以关键字template开场,然后是<>括起来的标识符,里面的标志符是我们希望推迟决定的数据类型。 用户利用这一模板来产生函数。
template<typename elemType>
void display(const string &msg, const vector<elemType>&vec)
{
cout<<msg;
for(int ix = 0;ix <vec.size();++ix)
{elemType t = vec[ix];
cout<<t<<’’l
}
}
关键字typename表示,elemType在函数中是一个暂时放置类型的占位符。
elemType可以是任意名称。
使用function template的方式和普通函数相似:
vector<int> ivec;
string msg;
//…
display(msg,ivec);
编译器会将elemType绑定为int,然后产生一份函数实例,
如果写
vector<string> ivec;
string msg;
//…
display(msg,ivec);
编译器会将elemType绑定为string.
一般而言,如果函数具有多种实现方式,我们可以将它重载,
如果我们希望函数主体不变,仅仅改变其中的数据类型,可以使用function template。
2.8 函数指针带来更大的弹性
函数指针(pointer to function),必须指明函数的返回值类型,参数列表。
例如:
const vector<int>* (*seq_ptr) (int);
seq_ptr是一个可以 指向返回值是const vector<int>*,参数是int的函数 的函数指针。
调用方式和函数相同:
const vector<int>*pseq = seq_ptr(pos);
取得函数的地址: 提供函数名即可:
seq_ptr = pell_seq; //将pell_seq()的地址给seq_ptr指针。
2.9 设定头文件
函数的定义只有一份,但可以有多份声明。
一个对象只能在程序中定义一次。
inlien函数的定义放在头文件中。
在file scope内定义的对象,如果可能被多个文件访问,就应该被声明在头文件中。
在对象前定义前加关键字extern可以使其变成声明:
extern const vector<int>* (*seq_array[seq_cnt])(int);
const object是一次定义规则下的例外,const object的定义只要一出文件之外就不可见。