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.赋值操作符何拷贝构造函数又同等重要的意义

原文地址:https://blog.51cto.com/13475106/2411427

时间: 2024-11-05 10:20:37

C++--函数对象的分析 经典问题的相关文章

(一)Python入门-5函数:03函数也是对象-内存分析

函数也是对象,内存底层分析: Python中,“一切都是对象”.实际上,执行def 定义函数后,系统就创建了相应的函数 对象.我们执行如下程序,然后进行解释: 1 #函数也是对象 2 def print_star(n): 3 print('*'*n) 4 5 print_star(3) 6 c = print_star 7 c(3) 8 9 print(id(print_star)) 10 print(id(c)) 11 print(type(c)) 上面代码执行 def 时,系统中会创建函数对

函数对象分析(二十九)

通过前面对 C++ 的学习,客户又有一个新的需求摆在我们的面前了.编写一个函数:函数可以获得斐波拉契数列每项的值:没调用一次便返回一个值:函数可根据需要重复使用. 我们之前在 C 语言中也讲过斐波拉契数列,相信这个很好实现了.那么我们就编写的程序如下 #include <iostream> using namespace std; int fib() {     static int a0 = 0;     static int a1 = 1;          int ret = a1;  

函数对象分析

首先我们看我们接到的一个用户需求: 编写一个函数: -函数可以获得斐波那契数列每项的值 -没调用一次返回一个值. -函数可以重复使用根据需要. 1 for(int i = 0; i<10; i++) 2 { 3 cout <<fib() << endl; 4 } 比如斐波那契函数,第一二次调用返回1 三次调用返回2,四次返回3.. 1 #include <iostream> 2 #include <string> 3 4 using namespace

C++ 数组操作符重载、函数对象分析、赋值操作符

string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using namespace std; //访问 string单个字符 int main() { string s = "1a2b3a4c"; int n = 0; for(int i=0 ; i< s.length() ; i++) { if(isdigit(s[i]))//isdigit 判断字符

JVM的内存区域划分,对象实例化分析

一.JVM程序具体执行过程 由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分.在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程:                                     如上图所示,Java源代码文件(.java后缀)经过Java编译器编译成为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行.在整个程序执行过程中,JVM会用一

函数对象+嵌套

#-*-coding:utf-8 -*-'''函数对象:函数是第一类对象,即函数可以当做数据传递 1.可以被引用 2.可以当做参数来传递 3.返回值可以是函数 4.可以当做容器类型的元素'''#1.可以被引用# def foo():# print('from foo')# func=foo# print(foo)# print(func)# func()#2.可以被当做参数传递# def foo():# print('from foo')# def bar(func):# print(func)

8、泛型程序设计与c++标准模板库5.函数对象

1.函数对象 函数对象是STL提供的第四类主要组件,它使得STL的应用更加灵活方便,从而增强了算法的通用性.大多数STL算法可以用一个函数对象作为参数.所谓"函数对象"其实就是一个行为类似函数的对象,它可以不需要参数,也可以带有若干参数,其功能是获取一个值,或者改变操作的状态. 在c++程序设计中,任何普通的函数和任何重载了调用运算符operator()的类的对象都满足函数对象的特征,因此都可以作为函数对象传递给算法作为参数使用. 以数值算法accumulate()为例子,介绍函数对象

java String.split()函数的用法分析

在java.lang包中有String.split()方法的原型是:public String[] split(String regex, int limit)split函数是用于使用特定的切割符(regex)来分隔字符串成一个字符串数组,函数返回是一个数组.在其中每个出现regex的位置都要进行分解.需要注意是有以下几点:(1)regex是可选项.字符串或正则表达式对象,它标识了分隔字符串时使用的是一个还是多个字符.如果忽略该选项,返回包含整个字符串的单一元素数组.(2)limit也是可选项.

C++ 函数对象

1.考虑下面的需求,从集合中找到一个与当前Student相等的学生,如下:int main(int argc, char* argv[]){ Student s1(20,"Andy"); Student s2(23,"Bill"); Student s3(28,"Caroline"); Student s4(27,"David"); Student s5(21,"Eric"); vector<Stud