C++ 中的可调⽤对象
C++中的可调⽤对象总结
可调用对象用处⼴泛:
- ⽐如在使⽤⼀些基于范围的模板函数时,如
sort(It first, It last, Compare cmp)
、all_of()
、find_if()
等),需要传⼊⼀个可调⽤对象客制化处理。 - 在处理⼀些回调函数、触发函数时,也会使⽤可调⽤对象。
满足以下条件的为可调用对象:
- 是一个函数或类成员函数
- 是一个函数指针
- 是一个重载operator()的类对象
- lambda表达式
- 是一个可转型为函数指针的类对象
- 是一个类成员函数指针
- bind表达式、std::function()
- 协程
普通函数
int add(int a, int b) {
return a + b;
}
int main() {
int num1, num2;
std::cout << "Enter two numbers: ";
std::cin >> num1 >> num2;
int sum = add(num1, num2);
std::cout << "The sum of " << num1 << " and " << num2 << " is: " << sum << s << "\n";
return 0;
}
类成员函数
#include <iostream>
using namespace std;
class Box{
public:
double length; // ⻓度
double breadth; // 宽度
double height; // ⾼度
// 成员函数声明
double getVolume(void);
void setLength( double len );
void setBreadth( double bre );
void setHeight( double hei );
};
// 成员函数定义
double Box::getVolume(void)
{
return length * breadth * height;
}
void Box::setLength( double len )
{
length = len;
}
void Box::setBreadth( double bre )
{
breadth = bre;
}
void Box::setHeight( double hei )
{
height = hei;
}
int main( )
{
Box box; // 声明 box,类型为 Box
double volume = 0.0; // ⽤于存储体积
// 详述
box.setLength(6.0);
box.setBreadth(7.0);
box.setHeight(5.0);
// 体积
volume = box.getVolume();
cout << "box 的体积:" << volume <<endl;
return 0;
}
类静态成员函数
类中的静态成员函数作⽤在整个类的内部,类静态成员函数属于类而非对象。静态成员函数只能访问对应类内部的静态数据成员(因为静态成员函数没有this指针)。类的static函数在类内声明、类外定义时,类内使用static
修饰,类外则不能加static
关键字,否则会出现编译错误。
class Box{
private:
int _non_static;
static int _static;
public:
int a(){
return _non_static;
}
static int b(){
//_non_static=0; 错误
//静态成员函数不能访问⾮静态成员变量
return _static;
}
static int f(){
//a(); (不对,静态成员函数不能访问⾮静态成员函数)
return b();
}
};
int Box::_static= 0;// static静态成员变量可以在类的外部修改
int main(){
Box box;
Box* pointer=&box;
box.a();
pointer->a();
Box::b(); // 类名::静态成员函数名
return 0;
}
与类成员函数的区别
- 静态成员函数没有
this
指针,只能访问静态成员(包括静态成员变量和静态成员函数)。 - 普通成员函数有
this
指针,可以访问类中的任意成员;⽽静态成员函数没有this
指针。
仿函数
仿函数就是重载了()
运算符的类对象,函数功能通过重载()
实现。(⾏为类似函数,故称仿函数)。实际上就是创建⼀个类,该类重载了()
运算符,使得类的实例可以像函数⼀样被调⽤。这允许你在函数对象内部保存状态,并在调⽤时执⾏操作。
简单示例
class Foo
{
void operator()()
{
cout << __FUNCTION__ << endl;
}
};
int main()
{
Foo a;
//定义对象调⽤
a.operator()();
//直接通过对象调⽤
a();
//通过临时对象调⽤
Foo()();
}
高级用法-状态保持
仿函数可以具有成员变量,因此在多次调用之间可以保持状态。这在算法需要记录或更新某些值的情况下非常有用。
考虑一个例子:对一个
vector
统计长度小于5的string的个数
优缺点
优点
- 状态保持:仿函数可以具有成员变量,因此在多次调用之间可以保持状态。
- 更灵活的接口设计:仿函数可以根据需要定制接口,以适应特定的算法或场景。例如,可以根据算法需要添加额外的成员函数或数据成员。
- 更好的封装:仿函数可以将数据和操作封装在一个单独的对象中,这有助于实现更清晰、更模块化的代码。
-
缺点
- 需要单独实现一个类
函数指针
与数据项相似,函数也有地址。函数的地址就是存储它的机器语⾔代码内存的开始地址。通常情况下,这些地址对⽤⼾⽽⾔并不重要,但对于程序⽽⾔,却很有⽤。⽐⽅说,可以编写将另⼀个函数的地址作为参数的函数,这样第⼀个函数就能够找到第⼆个函数,并运⾏它。与直接调⽤另⼀个函数相⽐,这种⽅法虽然很笨拙,但是它允许在不同的时间传递不同函数的地址,这也就意味着可以在不同的时间使⽤不同的函数。
获取函数地址
函数名,不加()
声明并调用函数指针
注意两种方式绑定函数的区别!
- 使用 using 声明函数指针
#include<iostream>
// 定义一个简单的函数
int add(int a, int b) {
return a + b;
}
int main() {
// 使用 using 声明定义函数指针类型
using AddFunctionPtr = int (*)(int, int);
// 创建函数指针变量并指向 add 函数
AddFunctionPtr my_add_function = &add;
// 使用函数指针调用 add 函数
int result = my_add_function(3, 4);
std::cout << "3 + 4 =<< result<< std::endl;
return 0;
}
- old style
#include<iostream>
// 定义一个简单的函数
int add(int a, int b) {
return a + b;
}
int main() {
// 使用 using 声明定义函数指针类型
int (*my_add_function )(int, int);
// 指向 add 函数
my_add_function = &add;
// 使用函数指针调用 add 函数
int result = my_add_function(3, 4);
// int result = (*my_add_function)(3, 4);// ok
std::cout << "3 + 4 =<< result<< std::endl;
return 0;
}
lambda表达式
std::function()
协程
原文地址:https://blog.csdn.net/weixin_51332735/article/details/140289645
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!