C++--函数对象的分析 经典问题
Q:客户的需求
1.函数可以获得斐波那契数列每项的值
2.每调用一次返回一个值
3.函数可根据需求重复使用
for(int i=0;i<10;i++){ cout<<fib()<<endl;}
代码示例
#include <iostream>#include <string>using namespace std;int fib(){ static int a0=0; static int a1=1; int ret=a1; a1=a0+a1; a0=ret; return ret;}int main(){ for(int i=0; i<10; i++) { cout << fib() << endl; } cout << endl; for(int i=0; i<5; i++) { cout << fib() << endl; } cout << endl; for(int i=0; i<5; i++) { cout << fib() << endl; } return 0;}
输出的结果如图所示
从代码以及运行结果我们看到一些存在的问题
1.静态局部变量处于函数内部,外界无法改变
2.函数位全局变量,是唯一的,无法多次独立使用
3.无法指定某个具体的数列作为初始值
解决方案:使用函数对象
1.使用具体的对象取代函数
2.该类的对象具备函数调用的行为
3.构造函数指定具体数列项的起始位置
4.多个对象相互对立的求解数列项
函数的调用操作符
1.只能通过类的成员函数重载
2.可以定义不同参数的多个重载函数
代码示例
#include <iostream>#include <string>using namespace std;class Fib{ int a0; int a1;public: Fib() { a0 = 0; a1 = 1; } Fib(int n) { a0 = 0; a1 = 1; for(int i=2; i<=n; i++) { int t = a1; a1 = a0 + a1; a0 = t; } } int operator () () { int ret = a1; a1 = a0 + a1; a0 = ret; return ret; }};int main(){ Fib fib; for(int i=0; i<10; i++) { cout << fib() << endl; } cout << endl; for(int i=0; i<5; i++) { cout << fib() << endl; } cout << endl; Fib fib2(10); for(int i=0; i<5; i++) { cout << fib2() << endl; } return 0;}
运行结果如图所示
从多次的运行结果可以看出,对之前存在的问题进行改正,完成了需求
小结
1.函数调用操作符是可以重载的
2.函数调用操作符只能通过类的成员函数重载
3.函数调用操作符可以定义不同参数的多个重载指针
4.函数对象用于在工程中取代函数指针
Q:关于赋值的疑问
1.编译器为每个类默认重载了赋值操作符
2.默认的赋值操作符仅完成浅拷贝
3.当需要进行深拷贝时必须重载赋值操作符
4.赋值操作符与拷贝构造函数有相同的存在意义
代码示例
#include <iostream>#include <string>using namespace std;class Test{ int* m_pointer;public: Test() { m_pointer = NULL; } Test(int i) { m_pointer = new int(i); } Test(const Test& obj) { m_pointer = new int(*obj.m_pointer); } void print() { cout << "m_pointer = " << hex << m_pointer << endl; } ~Test() { delete m_pointer; }};int main(){ Test t1 = 1; Test t2; t2 = t1; t1.print(); t2.print(); return 0;}
运行结果如图所示
分析:在代码中由于将t1赋值给t2,导致t1与t2指向的是同一个地址,而在使用完之后,对内存进行释放时对同一个地址释放了两次,这个操作在计算机内部会造成错误
Q:关于string的疑问
下面的代码输出是什么?
string s="123456";const char *p=s.c_str();cout<<p<<endl;s.append("abced");cout<<p<<endl;
如上所示的代码想完成的是在字符串123456后面添加abced
可实际的运行结果如图所示
分析
小结
1.在需要进行深拷贝的时候必须重载赋值操作符
2.赋值操作符何拷贝构造函数又同等重要的意义
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。