精华内容
下载资源
问答
  • C++ 函数调用操作符 () 、 函数对象

    千次阅读 2015-12-30 17:04:18
    除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式 this 指针)与操作符的操作数数目相同。函数调用操作符可以接受任意数目的操作数。 函数调用操作符通常结合函数对象一起使用,在STL排序中...


    除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式 this 指针)与操作符的操作数数目相同。函数调用操作符可以接受任意数目的操作数。

    重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象。又称仿函数。

    函数调用操作符通常结合函数对象一起使用,在STL排序中应用广泛。


    为什么函数对象比函数指针效率高 ?

    函数对象比函数指针高: 这是由于使用函数对象可以在编译时确定调用的函数,比运行时确定效率高些。而且使用函数对象还有机会内联展开,从而避免了函数调用的开销。(from:http://bbs.csdn.net/topics/350142727

    函数指针的主要性能缺点是 它的间接引用使其不能被内联。


    转自:重载函数调用操作符


    函数调用操作符是(),因此,此操作符的函数重载是operator()()。重载函数调用操作符的类对象称为函数对象或仿函数(functor),因为我们可以像使用函数名一样使用对象名。先来看一个简单的例子。下面是重载了函数调用操作符的一个类:

    class Area  
    {  
    public:  
        int operator()(int length, int width) { return length*width; }  
    }; 

    此类中的操作符函数计算一个面积,它是两个整数实参的乘积。为了使用此操作符函数,只需要创建一个类型为Area的对象,例如:

    Area area;                                     // Create function object
    int pitchLength(100), pitchWidth(50);  
    int pitchArea = area(pitchLength, pitchWidth); // Execute function call overload 

    第一条语句创建第三条语句中使用的area对象,第三条语句使用此对象来调用对象的函数调用操作符。在此例中,返回的是足球场的面积。

    当然,也可以将一个函数对象传递给另一个函数,就像传递任何其他对象一样。看看下面这个函数:

    void printArea(int length, int width, Area& area)  
    {  
        cout << "Area is " << area(length, width);  
    } 

    下面是使用此函数的语句:

    printArea(20, 35, Area()); 

    这条语句调用printArea()函数,前两个实参分别指定矩形的长和宽。第三个实参调用默认构造函数,以创建一个Area对象,函数中计算面积时要使用此Area对象。因此,函数对象提供了一种方式,可以将函数作为实参传递给另一个函数。与使用函数指针相比,这种方式既简单又容易。

    注意:第10章将学习std::function<>模板,它为传递函数提供了更大的灵活性。

    定义函数对象的类一般不需要数据成员,也没有定义的构造函数,因此创建和使用函数对象的开销是最小的。函数对象类通常也定义为模板,因为这会增加灵活性,本章稍后将会介绍这一点。


    以下为测试代码

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    
    //
    class FuncBase
    {
    public:
        void operator()(int i)
        {
            cout<<"FuncBase : "<<i<<endl;
        }
    };
    
    class FuncExtd : public FuncBase
    {
    public:
        void operator()(int i)
        {
            cout<<"FuncExtd : "<<i<<endl;
        }
    };
    
    void test(int i, FuncBase fun)
    {
        fun(i);
    }
    
    void test1(int i, FuncBase& fun)
    {
        fun(i);
    }
    
    //
    class FBase
    {
    public:
        virtual void operator()(int i)
        {
            cout<<"FBase : "<<i<<endl;
        }
    };
    
    class FExtd : public FBase
    {
    public:
        virtual void operator()(int i)
        {
            cout<<"FExtd : "<<i<<endl;
        }
    };
    
    void test2(int i, FBase fun)
    {
        fun(i);
    }
    
    void test3(int i, FBase& fun)
    {
        fun(i);
    }
    //
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        // 重载函数调用操作符 示声明为虚函数
        test(0, FuncBase());
        test(0, FuncExtd());
        test1(1, FuncBase());
        test1(1, FuncExtd());
    
        // 重载函数调用操作符 声明为虚函数
        test2(2, FBase());
        test2(2, FExtd());
        test3(3, FBase());
        test3(3, FExtd());
        return 0;
    }




    展开全文
  •  可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操作符。函数调用操作符必须声明为成员函数。一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别。 例如,可以定义名为 ...

     1、定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。

         可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操作符。函数调用操作符必须声明为成员函数。一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别。

    例如,可以定义名为 absInt 的结构,该结构封装将 int 类型的值转换为绝对值的操作:

    class absInt
    {
    public:
        int operator() (int val) 
        { 
            return val < 0 ? -val : val; 
        }
    };

    调用的情况如下所示:

    absInt m_abs;
    int num = m_abs(-5);

    2、函数对象常常用作算法的实参,下面是一个简单的例子:

    比如我们有个存储字符串的vector<string> words; 我们想计算其中字符数大于6的个数, 我们现在使用标准库的函数count_if来计算. count_if最后传入处理函数,函数形式like this:

     bool funcName(const string &s) ;

    此函数只接受一个参数,并且是count_if来为你传入, 好,下面我们写个比较函数:

     // determine whether a length of a given word is 6 or more 
     bool GT6(const string &s) 
     { 
         return s.size() >= 6; 
     }

    这样来调用就ok了

    vector<string>::size_type wc = count_if(words.begin(), words.end(), GT6); 

    上面的程序将6固化在了GT函数的定义之中。理想的状况是我们可以和任意长度做比较,那么对上面的类进行一下改造就可以了:

     // determine whether a length of a given word is longer than a stored bound 
    class GT_cls 
    { 
    public: 
        GT_cls(size_t val = 0): bound(val) { } 
        bool operator()(const string &s){ return s.size() >= bound; } 
    private: 
        std::string::size_type bound; 
    }; 

    我们可以按照下面的方式来调用:

    //大于6个
    cout << count_if(words.begin(), words.end(), GT_cls(6)) << " words 6 characters or longer" << endl;
    //大于5个
    cout << count_if(words.begin(), words.end(), GT_cls(5)) << " words 5 characters or longer" << endl;
    //循环体
    for (size_t i = 0; i != 11; ++i) 
        cout << count_if(words.begin(), words.end(), GT(i))<< " words " << i << " characters or longer" << endl;

    3、上面展示给大家的是C++Primer第四版中的实例,有关函数对象的定义看到这里想必大家也已经很清楚了,可是在实际中是怎么用的估计不少人又犯难了。毕竟知道是一回事,而熟练使用则又是另外一回事。

          有可能大家会联想到函数指针,是的,如果你能想到这一步,那么说明你已经有一些功底了。如果还不知道函数指针,请看:函数指针及其应用。函数对象既然是一个“类对象”,那么我们当然可以在函数形参列表中调用它,它完全可以取代函数指针!如果说指针是C的标志,类是C++特有的,那么我们也可以说指针函数和函数对象之间的关系也是同前者一样的!(虽然有些严密)。当我们想在形参列表中调用某个函数时,可以先声明一个具有这种函数功能的函数对象,然后在形参中使用这个对象,他所作的功能和函数指针所作的功能是相同的,而且更加安全。

     

    #include <iostream>
    
    using namespace std;
    
    class FuncT{
    public:
        template<typename T>
        T operator() (T t1, T t2)
        {
            cout<<t1<<'+'<<t2<<'='<<t1+t2<<endl;
            return t1;
        }
    };
    template <typename T>
    T addFuncT(T t1, T t2, FuncT& funct)
    {
        funct(t1,t2);
        return t1;
    }
    
    int main()
    {
        FuncT funct;
        cout<<addFuncT<int>(2,4,funct)<<endl;
        cout<<addFuncT<double>(1.4,2.3,funct)<<endl;
    
        return 0;
    }
    
      上面程序运行的结果:


       看到了把,函数对象不仅能够达到函数指针能够达到的目的,并且在应用方面比函数指针更加灵活。
    展开全文
  • 可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操 作符。例如,可以定义名为 absInt 的结构,该结构封装将 int 类型的值转换 为绝对值的操作: struct absInt { int operator() (int ...
    函数对象和调用操作符
    
    可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操
    作符。例如,可以定义名为 absInt 的结构,该结构封装将 int 类型的值转换

    为绝对值的操作:


    struct absInt {
    int operator() (int val) {
    return val < 0 ? -val : val;
    }

    };


    这个类很简单,它定义了一个操作:函数调用操作符,该操作符有一个形参
    并返回形参的绝对值。
    通过为类类型的对象提供一个实参表而使用调用操作符,所用的方式看起来
    像一个函数调用:
    int i = -42;
    absInt absObj; // object that defines function call operator
    unsigned int ui = absObj(i); // calls absInt::operator(int)
    尽管 absObj 是一个对象而不是函数,我们仍然可以“调用”该对象,效果
    是运行由 absObj 对象定义的重载调用操作符,该操作符接受一个 int 并值并
    返回它的绝对值。
    函数调用操作符必须声明为成员函数。一个类可以定义函数调
    用操作符的多个版本,由形参的数目或类型加以区别。
    定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。


    PS: 转载自<C++ Primer>

    展开全文
  • 调用操作符函数对象

    千次阅读 2014-02-25 22:46:16
    什么是调用操作符函数对象呢?就是调用操作符看起来像是调用函数,如下设计的一个类,是用来求一个整数的绝对值的,如下类 struct absInt { int operator()(int a) { return (a )? -a: a; } }; 如下调用 ...

    引言

    什么是调用操作符和函数对象呢?就是调用操作符看起来像是调用函数,如下设计的一个类,是用来求一个整数的绝对值的,如下类

    struct absInt
    {
    	int operator()(int a) {
    		return (a < 0)? -a: a;
    	}
    };
    
    如下调用

    	int nVal = -1234;
    	absInt abs;
    	int nPosVal = abs.operator()(nVal);
    	int nabsVal = abs(nVal);
    这里使用的是abs(nval),看起来是不是函数的调用,而且还有形参呢,这里使用了重载操作符(),这里只有一个形参,所以默认使用abs()就是调用操作符(),而形参就是nVal,所以就看起来像函数调用。

    解说

    函数对象 functor,是可以实现operator ()的任何类类型。 此运算符称作”运算符应用程序运算符“。 标准模板库主要在容器和算法使用函数对象作为排序条件。函数对象提供两大优势条函数调用:

    (1)函数对象可以包含状态

    (2)函数对象属于类型并可用作模板参数

    创建函数对象

    若要创建功能对象,请创建一个类类型以及operator ()函数,例如:

    class Functor
    {
    public:
        int operator()(int a, int b)
        {
            return a < b;
        }
    };
    
    int main()
    {
        Functor f;
        int a = 5;
        int b = 7;
        int ans = f(a, b);
    }

    main 功能的最后一行显示如何调用函数对象,这看起来像是显示函数调用,但是,它实际调用Functor 中的 operator() 运算符函数。在调用函数对象和函数之间的相似之处就是对象的显示方式。

    函数对象和容器

    标准模板库。 <functional> 头文件包含一些函数对象。这些功能对象的一个用途是作为容器的排序依据的条件。 例如, set 容器声明如下所示:

    template <class Key,class Traits=less<Key>,class Allocator=allocator<Key> >
    class set
    
    第二个模板参数是函数对象less 此函数对象返回true ,如果第一个参数传递给它比传递的第二个参数小于。 因为一些容器进行排序的元素容器,需要比较两个元素方式,这样,使用函数对象完成的。 可以通过创建函数对象拥有排序容器的条件,并指定它在模板用于容器的列表。

    函数对象和算法

    为函数对象的另一使用在算法。 例如, remove_if 算法声明如下所示:

    template<class ForwardIterator, class Predicate>
        ForwardIterator remove_if(ForwardIterator _First, ForwardIterator _Last, Predicate _Pred);
    

    remove_if 的最后一个参数是返回布尔值的函数对象 如果函数对象的结果是 true,则元素通过迭代器_First_Last指向的范围中移除 。你可以使用<functional> 头文件中声明的任何函数对象作为参数_Pred ,当然你也可以创建自己的函数对象。





    展开全文
  • 调用操作符的重载与函数对象

    千次阅读 2012-09-11 17:29:40
    一:调用操作符重载:我们可以为类类型的对象重载调用操作符即小括弧”()“,定义了调用操作符的类,在使用定义的调用操作符时,行为就像是调用函数,所以这种对象称为函数对象,即行为类似函数的对象: 如下例子为...
  • 本篇文章是对C++中构造函数、拷贝构造函数、赋值操作符、析构函数调用过程进行了总结与分析,需要的朋友参考下
  • 使用类作用域操作符进行成员函数调用问题
  • 如果对象是通过new操作符创建的,则通过delete操作符调用析构函数。 复制构造函数: 形如foo_t(const foo_t& foo),以下情况复制构造函数均会被调用: 当对象按值返回时候(returned by value) 调用按值传参的函数...
  • 在我们调用构造函数时,会使用new操作符 + 构造函数,在这种方式调用构造函数时,会执行以下几个步骤: - 创建一个新对象 - 将构造函数的作用域赋给这个新对象,这时this指针就指向了这个对象 - 执行构造函数...
  • 类的那些函数~~~
  • 派生类中怎样调用基类的输出操作符重载函数,想输出基类的私有成员,利用子类的对象
  • 拷贝构造函数调用重载赋值操作符,重载赋值操作符调用拷贝构造函数的写法都是没有意义的。 首先: 拷贝构造函数的存在意义--------是通过已有的对象构造新的对象,构造完毕后才有两个对象; 重载赋值操作符的...
  • C++中构造函数、复制构造函数和赋值操作符三者分别何时被调用很容易让人犯迷糊,下面结合例子就这个问题讨论一下。 假设我们有如下代码段:#include #include using namespace std;class Foo {public: Foo() { ...
  • 从面相对象编程的角度考虑,拷贝构造函数调用重载赋值操作符,重载赋值操作符调用拷贝构造函数的写法都是没有意义的。应该避免。 Don't try to implement one of the copying functions in terms of the other. ...
  • C++操作符函数

    千次阅读 2016-06-10 22:33:16
    操作符函数语法: 返回类型 operator操作符(参数列表) 操作符可以+ - * % /等运算符,这些操作符作为类操作符使用时仍然遵守它们被用作普通...1.如果操作符函数声明为成员函数调用函数的对象将成为左操作数。当操
  • 如何让new操作符不分配内存,只调用构造函数 转载▼ 如何让new操作符不分配内存,只调用构造函数 收藏  问题:c++中的new操作符 通常完成两个工作 分配内存及调用相应的构造出世核函数。 请问:...
  • 为什么有的操作符重载函数只能是成员函数?

    千次阅读 多人点赞 2017-12-16 15:32:45
    对于赋值运算符来说,我们知道一个c++类,程序员如果没有为其定义了赋值操作符重载函数,编译器也会隐式的定义,这样倘若再定义全局赋值运算符重载函数,将会发生二义性。即使编译器允许这样的定义手法,在调用的...
  • 拷贝构造函数和赋值操作符

    千次阅读 2014-07-19 19:29:34
    假设有一个如下的MyClass类: class MyClass { public: //构造函数 //拷贝构造函数 MyClass(const MyClass& that) : int_data_(that.int_data_), dbl_data_(that.dbl_data_), ... //赋值操作符 M
  • C++操作符重载

    千次阅读 2012-11-18 21:04:41
    除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同。函数调用操作符可以接受任意数目的操作数。   大多数操作符都可以重载,所以我列出不能重载的操作符,一共...
  • C++类—重载操作符

    千次阅读 2014-09-29 16:13:00
    重载操作符是具有特殊名称的函数:保留字operator后接定义的操作符符号。如: [cpp] view plaincopy ...除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针
  • 关于操作符函数的区别

    千次阅读 2015-07-30 13:44:55
    (1)操作符函数处理的阶段不同,操作符会在编译阶段处理(例如sizeof,会在编译阶段计算出值,以立即数的形式存放到代码段中),而函数则会在代码段中以call的形式去调用,如下代码所示: int functionA() { ...
  • 重写操作符函数一般定义成类的成员函数或友元函数。 二.操作符重载原则: 1.不能改变运算符的初始意义。2.不能改变运算符的参数数目。如重载运算符+时只用一个操作数是错误的。3.运算符函数不能包括缺省的参数...
  • 字符串操作符:Perl中的字符串操作符为 . ,用于将两个字符串拼接起来。此运算产生的字符串可以继续用来运算或储存到变量里。如:  "hello" . "world" # 等同于 "helloworld"  "hello" . " " . "world" # 等同...
  • 问题:c++中的new操作符 通常完成两个工作 分配内存及调用相应的构造函数。 请问: 1)如何让new操作符不分配内存,只调用构造函数? 2) 这样的用法有什么用? 解答:(要求new显式调用构造函数,但不分配内存。)...
  • 在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋值操作符。我就斗胆将他们命名为六大函数好了。 一、构造函数 c++primer中说过:构造函数是特殊的...
  • js Boolean函数和相等操作符规则

    千次阅读 2017-03-01 22:56:59
    Boolean函数在不同的参数下的返回值: 数据类型 转换为true的值 转换为false Boolean true false String 非空字符串 “”(空字符串) Number 非零数值(包括无穷大) 0和NaN Object 任何对象 null ...
  • Kotlin扩展函数与重载操作符解析

    千次阅读 2017-06-15 17:58:06
    扩展函数可以称为Kotlin的核心,标准库里到处充斥着扩展函数和高阶函数。然而标准库中扩展函数看起来都是高深莫测,一脸懵逼。本文教你如何理解扩展函数

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 684,416
精华内容 273,766
关键字:

函数调用操作符