函数指针
定义一个函数指针的方法其实跟定义一个普通指针的方法有点类似,对于普通函数和lanbda表达式的话,基本可以直接赋值给你定义的函数指针。
同一个函数指针 你甚至可以直接赋值,比如代码中注释的那行,效果跟重新定义一个函数指针一样。调用方法也直接是指针名+括号以及参数,而我所定义的函数以及指针都没有参数的,你也可以添加返回值类型以及参数,但指针也需要相对应的改变添加上参数、返回值类型。
在使用函数指针的时候,你把*换成&也行,但需要一开始就需要初始化,因为都知道引用的时候就需要初始化的。
void test()
{
std::cout << "hello I am test" << std::endl;
}
int main()
{
//普通函数
void (*func)() =test;
func();
//lambda表达式
//func = []() {std::cout << "I am lambda表达式" << std::endl; };
void(*func2)() = []() {std::cout << "I am lambda表达式" << std::endl; };
func2();
return 0;
}
其中函数指针不能指向仿函数,指向类成员方法时,是可以的,但是需要加上作用域,区分普通函数和类成员函数,函数指针定义时就需要区分好。
使用了&Base::test
和&Base::test1
来获取成员函数和静态函数的地址,并将它们分别赋值给func
和func2
指针
class Base
{
public:
void test()
{std::cout << "I am Base::test" << std::endl;}
static void test1()
{std::cout << "I am Bass::test1" << std::endl;}
};
int main()
{
//指向成员普通函数的话 比较麻烦,因为按照正常的话 成员方法调用你是需要实例化一个对象的
//另外使用成员函数指针时,需要确保使用正确的语法来调用成员函数
void (Base::*func)() = &Base::test;
Base ins;
(ins.*func)();
//指向静态函数的话就不需要作用域,大概是因为静态函数不属于某一个对象
//void (Base::*func2)() =&Base::test1;//会报错
void (*func2)() =&Base::test1;
func2();
return 0;
}
从代码中可以发现,在定义函数指针的时候,当你指向的是静态成员函数的话,指针类型好像不需要添加作用域,我试着加上去,发现报错,应该是不允许加的。指针指向成员函数时,需要加上取地址符,不过我发现指向的是静态成员函数的时候,是可以省略掉取地址符的。指向普通成员函数貌似比较麻烦,因为好像你即使定义好了一个指针,但是你还需要实例化一个对象,调用方法有点像是定义的指针属于对象的一个成员方法一样。
有一点需要注意的是。指针嘛,指向变量都是要取地址符的,好像在函数指针这一块也是一样的。
std::function方法
std::function解决了一些缺点,这个方法支持仿函数,跟定义普通函数指针还是有一些相近的。
#include<iostream>
#include<functional>
void test()
{
std::cout << "I am test" << std::endl;
}
class Base
{
public:
void test()
{
std::cout << "I am Base::test" << std::endl;
}
static void test1()
{
std::cout << "I am Bass::test1" << std::endl;
}
};
int main()
{
//指向普通函数 只需要在<>中初始化好函数类型就行了,前者为返回值类型,()中是所需参数。
std::function<void(void)>p=test;
p();
//类成员方法
std::function<void(void)> p1 = &Base::test1;//传值的时候 静态成员方法还是一样
p1();
Base ins;
//使用了std::function方法后,发现传值的方式不一样了,std还提供了一个bind方法,直接把
//成员函数以及实例化对象绑定到一起了,后期调用也不需要那么麻烦了。
std::function<void(void)> p2 = std::bind(&Base::test, &ins);
p2();
//lambda表达式
//该方法依旧
std::function<void(void)> p3 = []() {std::cout << "I am lambda" << std::endl; };
p3();
return 0;
}
标准库提供std::function方法,用起来确实比简单的函数指针方便很多,特别是在指向类成员方法的时候,直接和实例化的对象绑定,后期调用可以直接使用额,而不需要像函数指针一样麻烦得很,而标准库也提供了一个bind函数给我们用于绑定方法和对象。当然,对象还是需要一开始就实例化好。