1 不一样的斐波那契数列
我们现有有这样一个需求:
- 获取斐波那契数列每项的值
- 每调用一次返回一个值
- 函数可根据需要重复使用
使用方式如下所示:
我们可以通过使用静态变量的方法解决这个问题。代码如下:
// 23-1.cpp
#include<iostream>
using namespace std;
int Fib()
{
static int a0 = 0;
static int a1 = 1;
int ret = a1;
a1 = a1 + a0;
a0 = ret;
return ret;
}
int main()
{
for(int i = 0; i < 10; i++)
{
cout << Fib() << " ";
}
cout << endl;
for (int i = 0; i < 5; i++)
{
cout << Fib() << " ";
}
cout << endl;
return 0;
}
我们在函数 Fib() 中定义了两个 static 变量,一个保存当前值,一个保存当前值的前一个数值。static 变量具有全局声明周期,这样每调用一次就可以得到下一个斐波那契数。
编译运行:
$ g++ 23-1.cpp -o 23-1
$ ./23-1
1 1 2 3 5 8 13 21 34 55
89 144 233 377 610
上面的代码存在一些问题:第一,函数一旦开始,我们就不能重新从头打印斐波那契数列。第二,我们无法指定从某一项开始打印。
2 函数对象–重载函数调用操作符()
今天的主角就诞生了,他就是函数对象
- 使用具体的类对象取代函数,类对象具备函数调用行为
- 构造函数指定具体的数列的起始位置
- 多个对象相互独立的求解数列
怎么完成这些功能呢?通过重载操作符(())来完成
- 只能通过成员函数完成,函数之间可以根据参数重载
下面我们就开看一下神奇的解决方案长什么样呢?
// 23-2.cpp
#include<iostream>
using namespace std;
class Fib
{
public:
Fib(): a0(0), a1(1){}
Fib(int n)
{
a0 = 0;
a1 = 1;
for (int i = 2; i <= n; i++)
{
int tmp = a1;
a1 = a0 + a1;
a0 = tmp;
}
}
int operator () ()
{
int ret = a1;
a1 = a0 + a1;
a0 = ret;
return ret;
}
private:
int a0, a1;
};
int main()
{
Fib f;
for (int i = 0; i < 10; i++)
{
cout << f() << " ";
}
cout << endl;
for (int i = 0; i < 5; i++)
{
cout << f() << " ";
}
cout << endl;
Fib f2(10);
for (int i = 0; i < 5; i++)
{
cout << f2() << " ";
}
cout << endl;
return 0;
}
我们在类中重载括号操作符,可以使得对象可以和函数有类似的用法。类中重载了构造函数,Fib(int n) 可以指定斐波那契数列的其实数列。同时,不同的对象可以打印不同的数列。不知道你感受到它的神奇了吗?
编译运行:
$ g++ 23-2.cpp -o 23-2
$ ./23-2
1 1 2 3 5 8 13 21 34 55
89 144 233 377 610
55 89 144 233 377
3 小结
1、函数调用操作符可以重载,且只能通过成员函数实现
2、函数对象早工程中用于取代函数指针