函数指针
函数指针说白了就是一个指向函数地址的指针,因为我们对函数的调用,其实就是取函数所在的地址!函数指针定义方式为:
函数返回值类型 (指针变量名)(函数参数列表);
#include<iostream>
int SUM(int a,int b){
return a+b;
}
//typedef int(*SumFunc)(int x, int y); //建议这种方式,调用看起来也舒服
int(*SumFunc)(int x, int y);
int main(){
//SumFunc sum = SUM;
SumFunc = SUM;
//int ret = sum(1,2);
int ret = (*SumFunc)(1,2); //为什么要用*,因为取地址 解引用
std::cout<< ret<<std::endl;
}
函数对象
函数对象,也就是 Function Object
, 也被称为 Functor
,它可以被当作一个函数来调用。通常指重载了 operator()
的类对象。
class FuncObjType
{
public:
void operator() (std::string str)
{
cout<<"Hello "<<str<<endl;
}
};
int main(){
FuncObjType obj; //函数对象
obj("C++"); //就会输出Hello C++!
}
该调用语句在形式上跟以下函数的调用完全一样:
void val()
{
cout<<"Hello C++!"<<endl;
}
既然用函数对象与调用普通函数有相同的效果,为什么还有搞这么麻烦定义一个类来使用函数对象?
主要在于函数对象有以下的优势:
- 可以定义成员变量(作为自己的状态),这样函数对象多次调用时可以使用这个状态。普通函数除非使用全局变量
- 函数对象有类型
Lambda
最重要的作用就是可以创建匿名函数对象,就无需写一个普普通通的函数类,然后又重载一个括号运算符。
#include<vector>
#include<vector>
#include<iostream>
#include<algorithm>
int main()
{
int count = 0;
std::vector<std::string> words{ "An", "ancient", "pond" };
std::for_each(words.cbegin(), words.cend(),
[&count](const std::string& word)
{
if(isupper(word[0])) {
std::cout << word << " " << count << std::endl;
count++;
}
});
}
这样的代码在编译时,lambda表达式会自动转变成一个类——它每一个成员变量都对应着一个捕获的变量。这个类根据lambda表达式的参数列表重载了operator()
,一个可能的实现如下:
class lambda_implementation {
public:
lambda_implementation(int& n) : count_(n) {}
void operator()(const std::string& word) const
{
if(isupper(word[0]))
{
std::cout << word << " " << count << std::endl;
count_++;
}
}
private:
int& count_;
}
std::function
std::function
是一个函数包装器模板,一个 std::function
类型对象可以包装以下类型:
- 函数指针
- 类成员函数指针 (如使用
std::bind
传递) - 函数对象(定义了
operator()
操作符的类对象)
//声明一个模板
typedef std::function<int(int)> Functional;
//normal function
int TestFunc(int a)
{
return a;
}
//lambda expression
auto lambda = [](int a)->int{return a;};
//functor仿函数
class Functor
{
public:
int operator() (int a) //必须重载()
{
return a;
}
};
//类的成员函数和类的静态成员函数
class CTest
{
public:
int Func(int a)
{
return a;
}
static int SFunc(int a)
{
return a;
}
};
int main(int argc, char* argv[])
{
Functional obj = TestFunc;
//封装普通函数
int res = obj(0);
cout << "normal function : " << res << endl;
//封装lambda表达式
obj = lambda;
res = obj(1);
cout << "lambda expression : " << res << endl;
//封装仿函数
Functor functorObj;
obj = functorObj;
res = obj(2);
cout << "functor : " << res << endl;
//封装类的成员函数
CTest t;
obj = std::bind(&CTest::Func, &t, std::placeholders::_1);
res = obj(3);
cout << "member function : " << res << endl;
//类的static方法
obj = CTest::SFunc;
res = obj(4);
cout << "static member function : " << res << endl;
return 0;
}
std::bind就是可以创造闭包的工具,一般配合std::function使用。(闭包:在函数式编程中,通过组合现有的函数,可以创造出新的函数。)
#include<algorithm>
class Foo
{
public:
void methodA();
void methodInt(int a);
};
class Bar
{
public:
void methodB();
};
void main()
{
std::function<void()> f1; // 无参数,无返回值
Foo foo;
f1 = std::bind(&Foo::methodA, &foo);
f1(); // 调用 foo.methodA();
Bar bar;
f1 = std::bind(&Bar::methodB, &bar);
f1(); // 调用 bar.methodB();
f1 = std::bind(&Foo::methodInt, &foo, 42);
f1(); // 调用 foo.methodInt(42),只是入参给写死了,有些场景可能需要
std::function<void(int)> f2; // int 参数,无返回值
f2 = std::bind(&Foo::methodInt, &foo, _1);
f2(53); // 调用 foo.methodInt(53);
}
...