可调用对象有一下几种定义:
C++中可调用对象的虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一了可调用对象的各种操作。
不同类型可能具有相同的调用形式,如:
// 普通函数 int add(int a, int b){return a+b;} // lambda表达式 auto mod = [](int a, int b){ return a % b;} // 函数对象类 struct divide{ int operator()(int denominator, int divisor){ return denominator/divisor; } };
上述三种可调用对象虽然类型不同,但是共享了一种调用形式:
int(int ,int)
std::function就可以将上述类型保存起来,如下:
std::function<int(int ,int)> a = add; std::function<int(int ,int)> b = mod ; std::function<int(int ,int)> c = divide();
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
double my_divide (double x, double y) {return x/y;} auto fn_half = std::bind (my_divide,_1,2); std::cout << fn_half(10) << '\n'; // 5
struct Foo { void print_sum(int n1, int n2) { std::cout << n1+n2 << '\n'; } int data = 10; }; int main() { Foo foo; auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1); f(5); // 100 }
默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。
#include <iostream> #include <functional> #include <vector> #include <algorithm> #include <sstream> using namespace std::placeholders; using namespace std; ostream & print(ostream &os, const string& s, char c) { os << s << c; return os; } int main() { vector<string> words{"helo", "world", "this", "is", "C++11"}; ostringstream os; char c = ' '; for_each(words.begin(), words.end(), [&os, c](const string & s){os << s << c;} ); cout << os.str() << endl; ostringstream os1; // ostream不能拷贝,若希望传递给bind一个对象, // 而不拷贝它,就必须使用标准库提供的ref函数 for_each(words.begin(), words.end(), bind(print, ref(os1), _1, c)); cout << os1.str() << endl; }
通过下面的例子,熟悉一下指向成员函数的指针的定义方法。
#include <iostream> struct Foo { int value; void f() { std::cout << "f(" << this->value << ")\n"; } void g() { std::cout << "g(" << this->value << ")\n"; } }; void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) { (foo1->*fun)(); // call fun on the object foo1 (foo2->*fun)(); // call fun on the object foo2 } int main() { Foo foo1{1}; Foo foo2{2}; apply(&foo1, &foo2, &Foo::f); apply(&foo1, &foo2, &Foo::g); }
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!