1. 函数和结构
为结构编写函数比为数组辨析额函数要简单得多。虽然结构变量和数组一样,都可以存储多个数据项,但涉及到函数时,结构变量的行为更接近于基本的单值变量。也就是说,与数组不同,结构将其数据组合成单个实体或数据对象,该实体被视为一个整体。可以将结构按值传递,这时函数将使用原始结构的副本。另外,函数可以返回结构。与数组名就是数组第一个元素的地址不同的是,结构名只是结构的名称,要获得结构的地址,必须使用地址运算符 & 。
struct travel_time
{
int hours;
int mins;
};
travel_time sum(travel_time t1, travel_time t2)
{
travel_time total;
total.mins = (t1.mins + t2.mins) % Mins_per_hr;
total.hours = (t1.hours + t2.hours) +
(t1.mins + t2.mins) / Mins_per_hr;
return total;
}
2. 函数和 string 对象
虽然 C-风格字符串和 string 对象的用途几乎相同,但与数组相比,string 对象与结构更相似。可以将结构作为完整的实体传递给函数,也可以将对象作为完整的实体进行传递。如果需要多个字符串,可以声明一个 string 对象数组,而不是二维 char 数组。
void display(const string sa[], int n)
{
for (int i = 0; i < n; i++)
cout << i + 1 << ": " << sa[i] << endl;
}
3. 函数和 array 对象
在 C++ 中,类对象是基于结构的,因此结构编程方面的有些考虑因素也适用于类。比如,可以按值将对象传递给函数,在这种情况下,函数处理的是原始对象的副本。另外,也可以传递指向对象的指针,这让函数能够操作原始对象。
void fill(array<double, Seasons> * pa)
{
for (int i = 0; i < Seasons; i++)
{
cout << "Enter " << Snames[i] << " expenses: ";
cin >> (*pa)[i];
}
}
void show(array<double, Seasons> da)
{
double total = 0.0;
cout << "\nEXPENSES\n";
for (int i = 0; i < Seasons; i++)
{
cout << Snames[i] << ": $" << da[i] << endl;
total += da[i];
}
cout << "Total Expenses: $" << total << endl;
}
4. 递归
C++ 函数可以调用自己(然而,与 C 语言不同的是, C++ 不允许 main() 调用自己),这种功能被称为递归。递归在特定的编程(例如人工智能)中是一种重要的工具。
如果递归函数调用自己,则被调用的函数也将调用自己,这将无线循环下去,除非代码中包含终止调用链的内容。通常的方法将递归调用放在 if 语句中。例如 void 类型的递归函数 recurs() 的代码如下:
void recurs(argumentlist)
{
statements1
if (test)
recurs(arguments)
statements2
}
test 最终将为 false,调用链将断开。
5. 函数指针
基础知识
假设要设计一个名为 estimate() 的函数,估算编写指定行数的代码所需的时间,并且希望不同的程序员都将使用该函数。对于所用的用户来说,estimate() 中一部分代码都是相同的,但该函数允许每个程序员提供自己的算法来估算时间,为实现这种目标,采用的机制是,将程序员要使用的算法函数的地址传递给 estimate() 。为此,必须完成下面的工作:
- 获取函数的地址;
- 声明一个函数指针;
- 使用函数指针来调用函数。
获取函数地址
只要使用函数名即可,也就是说,如果 think() 是一个函数,则 think 就是该函数的地址。要将函数作为参数进行传递,必须传递函数名。
声明函数指针
声明指向某种数据类型的指针时,必须制定指针指向的类型。声明指向函数的指针时,也必须指定指针指向的函数类型。
假设有如下原型:
double pam(int);
则正确的指针类型声明如下:
double (*pf)(int);
pf 指向一个需要一个 int 参数,并返回 double 类型的函数。double *pf(int)
意味着 pf()
是一个返回指针的函数;而 (*pf)(int)
意味着 pf 是一个指向函数的指针。
正确声明 pf 后,便可以将相应函数的地址赋给它:
double pam(int);
double (*pf)(int);
pf = pam;
注意,pam() 的特征表和返回类型必须与 pf 相同。
使用指针来调用函数
(*pf)
扮演的角色与函数名相同,因此使用 (*pf)
时,只需将它看做函数名即可。