【足迹C++primer】48、函数引用操作符

函数引用操作符

struct absInt
{
    int operator()(int val) const
    {
        cout<<val<<"<->!!!"<<endl;
        return val<0 ? -val : val;
    }
};
void fun1()
{
    int i=-42;
    absInt absObj;
    int ui=absObj(i);
}

Function-Object Classes with State

函数对象类的状态

class PrintString
{
public:
    PrintString(ostream &o=cout, char c=' '):os(o), sep(c) {}   //构造函数
    void operator()(const string &s) const {os<<">>>>-----<<<<"<<s<<sep<<"yeah!"<<endl;}   //函数操纵符
    void operator()(const int i, const string &s1, const string &s2) const
    {
        if(i)
        {
            os<<"3 个参数 cutter_point-"<<s1<<endl;
        }
        else
        {
            os<<"3 个参数 cutter_point-"<<s2<<endl;
        }
    }

private:
    ostream &os;    //输出流
    char    sep;
};

void fun2()
{
    string s="cutter_point";
    PrintString printer;        //默认构造函数
    printer(s);     //调用操作符函数,输出:>>>>-----<<<<cutter_point yeah!
    PrintString errors(cerr, '\n'); //上面yeah!前面变成换行
    errors(s);

    vector<string> vs;
    for(size_t i=0 ; i != 7 ; ++i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        vs.push_back(ss.str());
    }
    for_each(vs.begin(), vs.end(), PrintString(cerr, '\n'));

    PrintString three;
    three(1, "我就是这么屌!", "没有,也就一般般啦!");
}

14.8.1. Lambdas Are Function Objects

void fun3()
{
    vector<string> words;
    for(size_t i=0 ; i != 7 ; ++i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    stable_sort(words.begin(), words.end(), [](const string &a, const string &b){return a.size()<b.size();});
    for_each(words.begin(), words.end(), PrintString(cout, '3'));
}

class ShorterString
{
public:
    bool operator()(const string &s1, const string &s2) const
    {return s1.size()<s2.size(); }
};

void fun4()
{
    vector<string> words;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    stable_sort(words.begin(), words.end(), ShorterString());
    for(vector<string>::iterator it=words.begin() ; it != words.end() ; ++it)
        cout<<*it<<"\t";
}

Classes Representing Lambdas with Captures

void fun5()
{
    vector<string> words;
    vector<string>::size_type sz=5;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    //得到一个指向第一个s.size()>sz的元素
    auto wc=find_if(words.begin(), words.end(), [sz](const string &a){return a.size() >= sz;});
    for(vector<string>::iterator it=words.begin() ; it != words.end() ; ++it)
        cout<<*it<<"\t";
    if(wc != words.end())
    {
        cout<<"wc:"<<*wc<<endl;
    }

}

class SizeComp
{
public:
    SizeComp(size_t n):sz(n) {} //构造函数
    bool operator()(const string &s) const {return s.size()>=sz;}
private:
    size_t sz;
};

void fun6()
{
    vector<string> words;
    vector<string>::size_type sz=6;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    //得到一个指向第一个s.size()>sz的元素
    auto wc=find_if(words.begin(), words.end(), SizeComp(sz));
    ///这里为什么会引用operator()操作呢??

    cout<<endl;
    if(wc != words.end())
    {
        cout<<"wc:"<<*wc<<endl;
    }
}

14.8.2. Library-Defined Function Objects

void fun7()
{
    plus<int> intAdd;       //这个是可以加两个int型数字
    negate<int> intNegate;  //求相反数
    int sum=intAdd(10, 20); //结果30
    cout<<sum<<endl;
    sum=intNegate(intAdd(10, 20));  //结果-30
    cout<<sum<<endl;
    sum=intAdd(10, intNegate(10));  //结果0
    cout<<sum<<endl;
}

Using a Library Function Object with the Algorithms

void fun8()
{
    vector<string> svec={"i","like","china","so","much","I","can","just","do","it"};
    //通过一个临时的函数对象应用<操作对两个string
    sort(svec.begin(), svec.end(), greater<string>());
    //输出结果按字典位置排序,然后大写在后,递减排序
    for_each(svec.begin(), svec.end(), [](string &s){cout<<s<<"\t";});
}

通过指针直接操作内存的地址,来改变排序

void fun9()
{
    vector<string> svec={"i","like","china","so","much","I","can","just","do","it"};
    vector<string*> nameTable;
    for(vector<string>::iterator it=svec.begin() ; it != svec.end() ; ++it)
    {
        string* s=new string;   //这里new string一定要加!!,为了给s分配空间
        *s=*it;
        nameTable.push_back(s);
    }

//    sort(nameTable.begin(), nameTable.end(), [](string* a, string* b){return a<b;});
    sort(nameTable.begin(), nameTable.end(), less<string*>());
    //输出的是按内存位置来输出的
    for(vector<string*>::iterator it=nameTable.begin() ; it != nameTable.end() ; ++it)
        cout<<*(*it)<<"\t";
}

14.8.3. Callable Objects and function

可调用对象和函数

Different Types Can Have the Same Call Signature

int add(int i, int j) {return i+j;}
void fun10()
{
    auto mod=[](int i, int j){return i%j;};
}
struct div2 //这里不要用div好像是和stdlib.h冲突了
{
    int operator()(int denominator, int divisor){return denominator/divisor;}
};

//上面三个都是int(int, int)类型的

我们可以定义一个map,用string类型来关联相应的函数,用string作为标识

void fun11()
{
    auto mod=[](int i, int j){return i%j;};
    map<string, int(*)(int, int)> binops;   //这是一个函数指针,返回一个int类型
    //这里add是一个指向+运算的指针,div是不能这样加的,它不是指针
    binops.insert({"+", add});
    binops.insert({"%", mod});
//    binops.insert({"/", div2});
}

库函数类型

void fun12()
{
    function<int(int, int)> f1=add;     //函数指针,这个是加法
    function<int(int, int)> f2=div2();   //调用()操作符,这个是除法
    function<int(int, int)> f3=[](int i, int j) {return i*j;};  //lambda返回乘法
    cout<<f1(4,2)<<endl;    //6
    cout<<f2(4,2)<<endl;    //2
    cout<<f3(4,2)<<endl;    //8
}

void fun13()
{
    auto mod=[](int i, int j){return i%j;};
    map<string, function<int(int, int)>> binops=
    {
        {"+", add},{"-", std::minus<int>()},{"/", div2()},{"*", [](int i, int j){return i*j;}},
        {"%", mod}
    };  //这个map有五个元素,当我们索引这个map的时候,我们可以调用这五个函数类型

    cout<<"+ <--->"<<binops["+"](10, 5)<<endl;
    cout<<"- <--->"<<binops["-"](10, 5)<<endl;
    cout<<"/ <--->"<<binops["/"](10, 5)<<endl;
    cout<<"* <--->"<<binops["*"](10, 5)<<endl;
    cout<<"% <--->"<<binops["%"](10, 5)<<endl;
}

Overloaded Functions and function

重载的函数和功能

void fun14()
{
    map<string, function<int(int, int)>> binops;
    int (*fp)(int, int)=add;
    binops.insert({"+", fp});   //用函数指针来避免重载,或者同名函数的含糊不清
    //含有一个很好的办法就是使用lambda来消除歧义是非常好的
    binops.insert({"+", [](int a, int b){return add(a,b);}});

}

在新的库函数类是不相关的类命名为

unary_function和binary_function是较早的版本的一部分

标准库。这些类被更一般的结合使用函数取代

全代码!

/**
* 功能:函数引用操作符
* 时间:2014年7月18日16:11:45
* 作者:cutter_point
*/

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<sstream>
#include<string>
#include<map>
#include<functional>

using namespace std;

struct absInt
{
    int operator()(int val) const
    {
        cout<<val<<"<->!!!"<<endl;
        return val<0 ? -val : val;
    }
};

void fun1()
{
    int i=-42;
    absInt absObj;
    int ui=absObj(i);
}

/**
Function-Object Classes with State
函数对象类的状态
*/
class PrintString
{
public:
    PrintString(ostream &o=cout, char c=' '):os(o), sep(c) {}   //构造函数
    void operator()(const string &s) const {os<<">>>>-----<<<<"<<s<<sep<<"yeah!"<<endl;}   //函数操纵符
    void operator()(const int i, const string &s1, const string &s2) const
    {
        if(i)
        {
            os<<"3 个参数 cutter_point-"<<s1<<endl;
        }
        else
        {
            os<<"3 个参数 cutter_point-"<<s2<<endl;
        }
    }

private:
    ostream &os;    //输出流
    char    sep;
};

void fun2()
{
    string s="cutter_point";
    PrintString printer;        //默认构造函数
    printer(s);     //调用操作符函数,输出:>>>>-----<<<<cutter_point yeah!
    PrintString errors(cerr, '\n'); //上面yeah!前面变成换行
    errors(s);

    vector<string> vs;
    for(size_t i=0 ; i != 7 ; ++i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        vs.push_back(ss.str());
    }
    for_each(vs.begin(), vs.end(), PrintString(cerr, '\n'));

    PrintString three;
    three(1, "我就是这么屌!", "没有,也就一般般啦!");
}

/**
14.8.1. Lambdas Are Function Objects
*/
void fun3()
{
    vector<string> words;
    for(size_t i=0 ; i != 7 ; ++i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    stable_sort(words.begin(), words.end(), [](const string &a, const string &b){return a.size()<b.size();});
    for_each(words.begin(), words.end(), PrintString(cout, '3'));
}

class ShorterString
{
public:
    bool operator()(const string &s1, const string &s2) const
    {return s1.size()<s2.size(); }
};

void fun4()
{
    vector<string> words;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    stable_sort(words.begin(), words.end(), ShorterString());
    for(vector<string>::iterator it=words.begin() ; it != words.end() ; ++it)
        cout<<*it<<"\t";
}

/**
Classes Representing Lambdas with Captures
*/
void fun5()
{
    vector<string> words;
    vector<string>::size_type sz=5;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    //得到一个指向第一个s.size()>sz的元素
    auto wc=find_if(words.begin(), words.end(), [sz](const string &a){return a.size() >= sz;});
    for(vector<string>::iterator it=words.begin() ; it != words.end() ; ++it)
        cout<<*it<<"\t";
    if(wc != words.end())
    {
        cout<<"wc:"<<*wc<<endl;
    }

}

class SizeComp
{
public:
    SizeComp(size_t n):sz(n) {} //构造函数
    bool operator()(const string &s) const {return s.size()>=sz;}
private:
    size_t sz;
};

void fun6()
{
    vector<string> words;
    vector<string>::size_type sz=6;
    for(size_t i=8 ; i != -1 ; --i)
    {
        stringstream ss;
        ss<<i<<"-cutter_point";
        words.push_back(ss.str());
    }
    words.push_back("test排序");

    //得到一个指向第一个s.size()>sz的元素
    auto wc=find_if(words.begin(), words.end(), SizeComp(sz));
    ///这里为什么会引用operator()操作呢??

    cout<<endl;
    if(wc != words.end())
    {
        cout<<"wc:"<<*wc<<endl;
    }
}

/**************************************
14.8.2. Library-Defined Function Objects
**************************************/
void fun7()
{
    plus<int> intAdd;       //这个是可以加两个int型数字
    negate<int> intNegate;  //求相反数
    int sum=intAdd(10, 20); //结果30
    cout<<sum<<endl;
    sum=intNegate(intAdd(10, 20));  //结果-30
    cout<<sum<<endl;
    sum=intAdd(10, intNegate(10));  //结果0
    cout<<sum<<endl;
}

/**************************************
Using a Library Function Object with the Algorithms
**************************************/
void fun8()
{
    vector<string> svec={"i","like","china","so","much","I","can","just","do","it"};
    //通过一个临时的函数对象应用<操作对两个string
    sort(svec.begin(), svec.end(), greater<string>());
    //输出结果按字典位置排序,然后大写在后,递减排序
    for_each(svec.begin(), svec.end(), [](string &s){cout<<s<<"\t";});
}

//通过指针直接操作内存的地址,来改变排序
void fun9()
{
    vector<string> svec={"i","like","china","so","much","I","can","just","do","it"};
    vector<string*> nameTable;
    for(vector<string>::iterator it=svec.begin() ; it != svec.end() ; ++it)
    {
        string* s=new string;   //这里new string一定要加!!,为了给s分配空间
        *s=*it;
        nameTable.push_back(s);
    }

//    sort(nameTable.begin(), nameTable.end(), [](string* a, string* b){return a<b;});
    sort(nameTable.begin(), nameTable.end(), less<string*>());
    //输出的是按内存位置来输出的
    for(vector<string*>::iterator it=nameTable.begin() ; it != nameTable.end() ; ++it)
        cout<<*(*it)<<"\t";
}

/**************************************
14.8.3. Callable Objects and function
可调用对象和函数
**************************************/

/**
Different Types Can Have the Same Call Signature
*/
int add(int i, int j) {return i+j;}
void fun10()
{
    auto mod=[](int i, int j){return i%j;};
}
struct div2 //这里不要用div好像是和stdlib.h冲突了
{
    int operator()(int denominator, int divisor){return denominator/divisor;}
};

//上面三个都是int(int, int)类型的

/*
我们可以定义一个map,用string类型来关联相应的函数,用string作为标识
*/
void fun11()
{
    auto mod=[](int i, int j){return i%j;};
    map<string, int(*)(int, int)> binops;   //这是一个函数指针,返回一个int类型
    //这里add是一个指向+运算的指针,div是不能这样加的,它不是指针
    binops.insert({"+", add});
    binops.insert({"%", mod});
//    binops.insert({"/", div2});
}

/**
库函数类型
*/
void fun12()
{
    function<int(int, int)> f1=add;     //函数指针,这个是加法
    function<int(int, int)> f2=div2();   //调用()操作符,这个是除法
    function<int(int, int)> f3=[](int i, int j) {return i*j;};  //lambda返回乘法
    cout<<f1(4,2)<<endl;    //6
    cout<<f2(4,2)<<endl;    //2
    cout<<f3(4,2)<<endl;    //8
}

void fun13()
{
    auto mod=[](int i, int j){return i%j;};
    map<string, function<int(int, int)>> binops=
    {
        {"+", add},{"-", std::minus<int>()},{"/", div2()},{"*", [](int i, int j){return i*j;}},
        {"%", mod}
    };  //这个map有五个元素,当我们索引这个map的时候,我们可以调用这五个函数类型

    cout<<"+ <--->"<<binops["+"](10, 5)<<endl;
    cout<<"- <--->"<<binops["-"](10, 5)<<endl;
    cout<<"/ <--->"<<binops["/"](10, 5)<<endl;
    cout<<"* <--->"<<binops["*"](10, 5)<<endl;
    cout<<"% <--->"<<binops["%"](10, 5)<<endl;
}

/**
Overloaded Functions and function
重载的函数和功能
*/
void fun14()
{
    map<string, function<int(int, int)>> binops;
    int (*fp)(int, int)=add;
    binops.insert({"+", fp});   //用函数指针来避免重载,或者同名函数的含糊不清
    //含有一个很好的办法就是使用lambda来消除歧义是非常好的
    binops.insert({"+", [](int a, int b){return add(a,b);}});

}

/*
在新的库函数类是不相关的类命名为
unary_function和binary_function是较早的版本的一部分
标准库。这些类被更一般的结合使用函数取代
*/

int main()
{
    cout<<">>----------------fun1---------------------<<"<<endl;
    fun1();
    cout<<">>----------------fun2---------------------<<"<<endl;
    fun2();
    cout<<">>----------------fun3---------------------<<"<<endl;
    fun3();
    cout<<">>----------------fun4---------------------<<"<<endl;
    fun4();
    cout<<">>----------------fun5---------------------<<"<<endl;
    fun5();
    cout<<">>----------------fun6---------------------<<"<<endl;
    fun6();
    cout<<">>----------------fun7---------------------<<"<<endl;
    fun7();
    cout<<">>----------------fun8---------------------<<"<<endl;
    fun8();
    cout<<">>----------------fun9---------------------<<"<<endl;
    fun9();
    cout<<">>----------------fun12---------------------<<"<<endl;
    fun12();
    cout<<">>----------------fun13---------------------<<"<<endl;
    fun13();

    system("pause");
    return 0;
}

PS:今天早上有点晚了,不行,以后每天早上坚持至少8点开始,7点起床!!!努力,我要学的东西还很多,远远不够,时间如此紧迫,怎可徒费光阴!!!

时间: 2024-11-03 05:28:21

【足迹C++primer】48、函数引用操作符的相关文章

C++ Primer 学习笔记_26_操作符重载与转换(1)--可重载/不可重载的操作符、成员函数方式重载、友元函数方式重载

C++ Primer 学习笔记_26_操作符重载与转换(1)--可重载/不可重载的操作符.成员函数方式重载.友元函数方式重载 引言: 明智地使用操作符重载可以使类类型的使用像内置类型一样直观! 一.重载的操作符名 像任何其他函数一样,操作符重载函数有一个返回值和一个形参表.形参表必须具有操作符数目相同的形参.比如赋值时二元运算,所以该操作符函数有两个参数:第一个形参对应着左操作数,第二个形参对应右操作数. 大多数操作符可以定义为成员函数或非成员函数.当操作符为成员函数时,它的第一个操作数隐式绑定

C++ Primer 学习笔记_28_操作符重载与转换(3)--成员函数的重载、覆盖与隐藏、类型转换运算符、*运算符重载、-&gt;运算符重载

C++ Primer 学习笔记_28_操作符重载与转换(3)--成员函数的重载.覆盖与隐藏.类型转换运算符.*运算符重载.->运算符重载 一.成员函数的重载.覆盖与隐藏 对于类层次的同名成员函数来说,有三种关系:重载.覆盖和隐藏,理清3种关系,有助于写出高质量的代码. 1.成员函数的重载 重载的概念相对简单,只有在同一类定义中的同名成员函数才存在重载关系,主要特点时函数的参数类型和数目有所不同:但不能出现函数参数的个数和类型均相同,仅仅依靠返回值类型不同来区分的函数,这和普通函数的重载是完全一致

【足迹C++primer】14、函数匹配、函数指针

LinJM   2014_05_23 解决内存泄漏问题 在VS2010的Debug模式下面,点击运行,然后退出,之后会在输出框里面出现内存泄漏信息(如下图所示). Analysis:主要是new了之后没有delete相应的变量,所以,很明显就是要在不使用时delete掉这个变量.不过,有个问题,如下图所示: 我代码修改位置如下所示: 我把红下划线部分注释掉就不会出现上面那个问题,后来讨论分析才发现pBim现在分配给了pAdjustmentLyInfo,二者现在指向同一个内存空间,当我delete

【足迹C++primer】47、Moving Objects(1)

Moving Objects(1) * 功能:Moving Objects * 时间:2014年7月17日08:46:45 * 作者:cutter_point */ #include<iostream> #include<string> #include<memory> #include<utility> #include<vector> #include<algorithm> #include<set> #include

【足迹C++primer】38、关联容器操作(2)

关联容器操作(2) map的下标操作 map的下标操作 map和unordered_map容器提供了下标运算符合一个对应的at函数 对于一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不再容器中的关键字作为下标,会添加一个此关键字的元素到map中 map和unordered_map的下标操作 c[k] 返回关键字为k的元素,如果关键字k不再c中,添加一个关键字为k的元素,对其进行值初始化 c.at(k) 访问关键字为k的元素,带参数检测,如果k不再c重那么返回一

【足迹C++primer】26、顺序容器操作

顺序容器操作 向顺序容器添加元素 forward_list //有自己专有版本的insert和emplace: forward_list //不支持push_back和emplace_back vector, string //不支持push_front和emplace_front c.push_back(t), c.emplace_back(args) //在c的尾部创建一个值为t的或者由args创建的元素,返回void c.push_front(t), c.emplace_back(args

【足迹C++primer】54、继承类的范围,构造函数和拷贝控制

继承类的范围,构造函数和拷贝控制 当用派生类执行函数的时候,首先会在当前的类里面找 如果找不到就一级一级地往上找. Name Lookup Happens at Compile Time class Quote { public: Quote()=default; Quote(const string &book, double sales_price):bookNo(book), price(sales_price) {cout<<"Quote gouzhao functi

【足迹C++primer】39、动态内存与智能指针(3)

动态内存与智能指针(3) /** * 功能:动态内存与智能指针 * 时间:2014年7月8日15:33:58 * 作者:cutter_point */ #include<iostream> #include<vector> #include<memory> #include<string> using namespace std; /** 智能指针和异常 */ void f() { shared_ptr<int> sp(new int(42));

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载、!运算符重载、赋值运算符重载 、String类([]、 +、 += 运算符重载)、&gt;&gt;和&lt;&lt;运算符重载

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载.!运算符重载.赋值运算符重载 .String类([]. +. += 运算符重载).>>和<<运算符重载 一.++/--运算符重载 1.前置++运算符重载 成员函数的方式重载,原型为: 函数类型 & operator++(); 友元函数的方式重载,原型为: friend 函数类型 & operator++(类类型 &); 2.后置++运算符重载 成员函数的方式重载,原型为: