首页 > 编程语言 >C++函数指针详解

C++函数指针详解

时间:2024-10-03 08:51:24浏览次数:7  
标签:fp return 函数 int C++ 详解 fun 函数指针

概述

本文详细介绍了C/C++中的普通函数和类的成员函数的指针。结合C++代码示例讲解了函数指针作为其他函数的输入、返回值以及typedef如何提高代码可读性的实用技巧。对于类的成员函数(方法)指针,则分为静态和非静态两种情况。最后总结了普通函数、类的非静态成员函数、类的静态成员函数的声明、赋值和定义的C++语法以供查阅。

普通函数的指针

声明、定义和赋值

首先让我们来区别以下4条声明语句:

int x;      // x是一个int型的变量
int *x;     // x是一个指向int型变量的指针
int *x();   // x是一个返回int型指针的函数
int (*x)(); // x是一个函数指针,输入参数为空,返回类型为int型指针

因此,把一个名为fun的函数的声明语句变为函数指针变量pfun的声明语句,只需要将 fun 变为 (*pfun),其他的不变即可(注意:小括号必不可少!)。

double fun(string& str1, string &str2);       // 函数fun的声明
double (*pfun)(string& str1, string &str2);   // 函数指针变量pfun的声明

在C/C++中,数组变量的名字是一个指向该数组元素类型的指针常量(存放首元素的地址),类似地,函数的名字也表示一个指向该函数的指针常量(存放该函数入口地址):

int array[5];      // array是一个指向int的指针常量
int *p = array;    // p是一个指向int的指针变量,p = array合法
p[3];              // 等价于array[3]

void test(int a){ cout << "a=" << a << endl;}  // test是一个函数指针常量,输入参数int,返回类型void
void (*pf)(int);   // 声明函数指针pf: pf是一个输入参数int,返回void的函数的指针
pf = test;         // 将test函数地址赋值给pf(二者输入参数列表、返回类型必须一致)
pf(123);           // 等价于test(123)

有几点需要说明:

// 声明和赋值可以写在一起:
void (*pf)(int) = test;  

// 2种赋值方式:(等价)
pf = test;    // 直接函数名赋值
pf = &test;   // 函数名取地址赋值,等价于pf = test

// 2种调用方式:(等价)
pf(123);     // 直接pf接参数调用
(*pf)(123);  // 先对函数指针解引用,再接参数调用,等价于pf(123)

例1:

#include <iostream>
using namespace std;

int add(int x, int y){
	return x + y;
}

int substract(int x, int y){
	return x - y;
}

int main(){
	int (*fp)(int, int);       // 定义函数指针变量:fp
	fp = add;                  // 将同类型函数add赋值给fp
	cout << fp(1, 3) << endl; 
	cout << (*fp)(1, 3) << endl;   // 等价于fp(1,3)
	fp = &substract;           // 将同类型函数substract赋值给fp, 取地址符号"&"可加可不加
	cout << fp(1, 3) << endl; 
	cout << (*fp)(1, 3) << endl;   // 等价于fp(1,3)
	return 0;
}

输出:

4
4
-2
-2

重载的函数自动匹配类型

如果有同名的重载函数,编译器会自动选择类型匹配的一个:

#include <iostream>
using namespace std;

int add(int x, int y){  
	return x + y;
}

int add(int x, int y, int z){  // 重载
	return x + y + z;
}

int main(){	
	int (*fp)(int, int) = add;  // 编译器会自动选择add(int x, int y)与fp匹配
	cout << "1 + 2 = " << fp(1,2) << endl;

	int (*fp2)(int, int, int) = add;  // 编译器会自动选择add(int x, int y, int z)与fp2匹配
	cout << "1 + 2 + 3 = " << fp2(1,2,3) << endl;
	
	return 0;
}

输出:

1 + 2 = 3
1 + 2 + 3 = 6

类型复杂的函数指针和typedef的妙用

当一个函数的输入列表、返回列表较为复杂时,尤其是参数/返回值中还嵌套了函数指针时,代码的可读性将会大大下降。

1、输入参数包含函数指针

函数指针作为输入参数(形参)有两种写法:将输入参数int变为int (*pf)(int, int),表示输入参数为函数指针pf(指向函数类型为int (*pf)(int, int))。

  • void test(int fun(int, int)) // 直接把fun函数的声明写在参数的位置,在test内部fun作为形参变量,表示函数指针
  • void test(int (*pf)(int, int)) // 将函数指针的声明写在参数的位置,在test内部pf作为形参变量,与上面写法等价

例2:下面例子中的add2()和add3() 就是输入参数为函数声明/函数指针的两种等价写法。

#include <iostream>
using namespace std;

int add(int x, int y){  // 双参数函数add2:两个数相加
	return x + y;
}

int add2(int (*fun)(int, int), int x, int y, int z){ // 使用函数声明语句作为形参,构造三参数函数add2()
	return fun(fun(x,y),z);
}

int add3(int fun(int, int), int x, int y, int z){    // 与上面等价, 使用函数指针作为形参,构造三参数函数add3()
	return fun(fun(x,y),z);
}

int main(){	
	int (*fp)(int, int);
	fp = add;
	cout << "1 + 2 = " << fp(1,2) << endl;

	int (*fp2)(int (*fun)(int, int), int, int, int);  // 第一个参数是双参数函数指针,第二到四个参数为int
	fp2 = add2;    // fp2赋值为类型一致的函数名
	cout << "1 + 2 + 3 = " << fp2(fp,1,2,3) << endl;

	fp2 = add3;    // 与上面等价,add3和add2实际是一样的,都能被fp2接收
	cout << "4 + 5 + 6 = " << fp2(fp,4,5,6) << endl;
	
	return 0;
}

输出结果:

1 + 2 = 3
1 + 2 + 3 = 6
4 + 5 + 6 = 15

2、返回值为函数指针

函数指针作为返回值的写法:只需要将int fun(int)变成 int (*fun(int))(double, double), 表示fun(int)返回一个函数指针pf(指向类型为int (*pf)(double, double))。

  • int (*createAdd())(int, int); // 定义一个名为createAdd()的函数,输入参数为空,返回值为一个函数指针pTemp(其类型为int (pTemp)(int, int))
  • int (*createAlgorithm(int type))(int, int); // 定义一个名为createAlgorithm(int)的函数:输入参数为int,返回值为对应运算符的函数指针pTemp(其类型为int (*pTemp)(int, int))

例3:无参数输入的函数createAdd()函数返回一个函数指针:

#include <iostream>
using namespace std;

int add(int x, int y){  
	return x + y;
}

// 定义一个名为createAdd()的函数
// 输入参数为空
// 返回值为一个函数指针pTemp(其类型为int (*pTemp)(int, int))
int (*createAdd())(int, int){  
	return add;
}

int main(){	
	int (*fp)(int, int); // 声明一个函数指针fp
	fp = createAdd();    // fp接收createAdd()返回值,二者都是同类型的函数指针,匹配
	cout << "1 + 2 = " << fp(1,2) << endl;
	return 0;
}

输出:

1 + 2 = 3

例4:带参数输入的createAlgorithm(int type)函数返回一个函数指针:

#include <iostream>
using namespace std;

// 定义三种运算:空运算、加法、减法
int none(int , int ){  
	return 0;
}
int add(int x, int y){  
	return x + y;
}
int substract(int x, int y){  
	return x - y;
}

// 定义一个名为createAlgorithm(int)的函数:
// 输入参数为int,表示选择哪一种运算符(1为加法,2为减法)
// 返回值为对应运算符的函数指针pTemp(其类型为int (*pTemp)(int, int))
int (*createAlgorithm(int type))(int, int){  
	switch(type){
		case 1:
			return add;
			break;
		case 2:
			return substract;
			break;
		default:
			return none;
	}
}

int main(){	
	int (*fp)(int, int);   // 声明一个函数指针fp
	fp = createAlgorithm(1);   // fp接收createAlgorithm(1)返回值,二者都是同类型的函数指针,匹配
	cout << "1 + 2 = " << fp(1,2) << endl;
	fp = createAlgorithm(2);   // fp接收createAlgorithm(2)返回值,二者都是同类型的函数指针,匹配
	cout << "5 - 1 = " << fp(5,1) << endl;
	return 0;
}

输出:

1 + 2 = 3
5 - 1 = 4

例5:输入参数和返回参数都含有函数指针:(int (calculateAndTransfer(int (fun)(int, int), int x, int y))(int, int){...})

#include <iostream>
using namespace std;

int add(int x, int y){  
	return x + y;
}
int substract(int x, int y){  
	return x - y;
}

// 定义一个名为calculateAndTransfer(int)的函数:在内部执行一次计算,并且把输入的函数指针再返回,传递下去
// 输入参数为函数指针(其类型为int (*pTemp)(int, int))和两个int变量
// 返回值为同样的函数指针pTemp(其类型为int (*pTemp)(int, int))
int (*calculateAndTransfer(int (*fun)(int, int), int x, int y))(int, int){ 
	cout << "fun(x,y) = " << fun(x,y) << endl;
	return fun;
}

int main(){	
	int (*fp)(int, int);
	fp = calculateAndTransfer(add,1,2); 
	cout << "1 + 2 = " << fp(1,2) << endl;
	fp = calculateAndTransfer(substract,5,1);  
	cout << "5 - 1 = " << fp(5,1) << endl;
	return 0;
}

输出:

fun(x,y) = 3
1 + 2 = 3
fun(x,y) = 4
5 - 1 = 4

可见,当函数指针出现在输入参数或者返回值位置时,代码可读性将会大大下降,这不利于项目的开发和维护。

3、typedef提高代码可读性

3.1 typedef自定义类型别名

通过上面的例子发现,当函数输入参数或者返回值包含函数指针时,代码可读性将会大大降低。为了解决这个问题,C++中可以使用typedef预先给某一类型起别名,然后再用自定义的别名会写出更让人容易理解的代码。

函数/函数指针使用typedef的两种方式:

  • typedef int Fun(int, int); // 类型别名:Fun代表一类函数
  • **typedef int (PFun)(int, int); ** // 类型别名:PFun代表一类函数指针 (int (pf)(int, int))

第一种方式的Fun是自定义的函数别名,第二种方式的PFun是自定义的函数指针别名。在作为形参输入时,二种方式等价(编译器会自动把Fun转换为函数指针),但仍然推荐第二种方式,无需隐式转换,让人更容易理解。

3.2 用typedef重写:函数指针作为输入参数

例6、用typedef重写:函数指针作为输入参数:

#include <iostream>
using namespace std;

typedef int Fun(int, int);     // 类型别名:Fun代表一类函数 
typedef int (*PFun)(int, int); // 类型别名:PFun代表一类函数指针

int add(int x, int y){  // 双参数函数add2:两个数相加
	return x + y;
}

int add2(int (*fun)(int, int), int x, int y, int z){ // 利用双参数输入的fun(), 构造三参数函数add2()
	return fun(fun(x,y),z);
}

int add4(PFun fun, int x, int y, int z){    // 与add2等价, 利用typedef提高可读性,构造三参数函数add3()
	return fun(fun(x,y),z);
}

int add5(Fun fun, int x, int y, int z){    // 与add4等价, 函数名会被自动转换为函数指针作为形参 
	return fun(fun(x,y),z);
}

int main(){	
	// 函数指针直接使用:
	int (*fp)(int, int);
	fp = add;
	cout << "1 + 2 = " << fp(1,2) << endl;

	// 同上,但使用typedef提高可读性
	PFun fp2 = add;  // 与fp是同一类型
	cout << "1 + 2 = " << fp2(1,2) << endl;

	// 函数指针作为输入参数(形参)时,使用typedef的add4和add5的代码可读性比add2更高:
	cout << "1 + 2 + 3 = " << add2(fp2, 1, 2, 3) << endl;
	cout << "1 + 2 + 3 = " << add4(fp2, 1, 2, 3) << endl;
	cout << "1 + 2 + 3 = " << add5(fp2, 1, 2, 3) << endl;
	
	return 0;
}

3.3 用typedef重写:函数指针作为返回值:

以下两者为等价写法:都是定义一个名为createAlgorithm(int)的函数,输入参数为int,返回值为函数指针pTemp(其类型为int (*pTemp)(int, int))

  • int (createAlgorithm(int type))(int, int){ ...} // 不使用typedef,返回类型写法难以阅读
  • typedef int (*PFun)(int, int);
    PFun createAlgorithm(int type){ ... } // 可见,用typedef定义的类型PFun写法同一般的返回类型写法,更容易理解

例7:用typedef重写:函数指针作为返回值:

#include <iostream>
using namespace std;

// PFun是一个函数指针的类型别名,指向函数的类型为int (*pTemp)(int, int)
typedef int (*PFun)(int, int);

// 定义三种运算:空运算、加法、减法
int none(int , int ){  
	return 0;
}
int add(int x, int y){  
	return x + y;
}
int substract(int x, int y){  
	return x - y;
}

// 定义一个名为createAlgorithm(int)的函数:
// 输入参数为int,表示选择哪一种运算符(1为加法,2为减法)
// 返回值为对应运算符的函数指针pTemp(其类型为int (*pTemp)(int, int))
// 等价于:int (*createAlgorithm(int type))(int, int){  xxx }
PFun createAlgorithm(int type){ 
	switch(type){
		case 1:
			return add;
			break;
		case 2:
			return substract;
			break;
		default:
			return none;
	}
}

int main(){	
	PFun fp = createAlgorithm(1);   // fp接收createAlgorithm(1)返回值,二者都是同类型的函数指针,匹配
	cout << "1 + 2 = " << fp(1,2) << endl;
	fp = createAlgorithm(2);   // fp接收createAlgorithm(2)返回值,二者都是同类型的函数指针,匹配
	cout << "5 - 1 = " << fp(5,1) << endl;
	return 0;
}

输出:

1 + 2 = 3
5 - 1 = 4

注:类型别名除了typedef之外,还有using和decltype,都可以实现函数指针的别名定义。例如下面三条语句定义的PFun1, PFun2, PFun3等价。

例8:typedef、using和decltype三种等价写法:

#include <iostream>
using namespace std;

int add(int x, int y){  
	return x + y;
}

// 以下为类型别名的三种等价写法:
typedef int (*PFun1)(int, int);  // 类型别名:PFun1代表一类函数指针
using PFun2 = int (*)(int, int); // 类型别名:PFun2与PFun1等价
typedef decltype(add) *PFun3;    // 类型别名:PFun3与PFun1等价

int main(){	
	PFun1 fp1 = add;  
	PFun2 fp2 = add;  
	PFun3 fp3 = fp2;  
	cout << "1 + 2 = " << fp1(1,2) << endl;
	cout << "1 + 2 = " << fp2(1,2) << endl;
	cout << "1 + 2 = " << fp3(1,2) << endl;
	return 0;
}

输出:

1 + 2 = 3
1 + 2 = 3
1 + 2 = 3

3.4 用typedef重写:输入参数和返回参数都含有函数指针:以下两种写法等价:

  • int (*calculateAndTransfer(int (*fun)(int, int), int x, int y))(int, int)
  • typedef int (*PFun)(int, int);
    PFun calculateAndTransfer(PFun fun, int x, int y); // typedef大大提高可读性

例9:用typedef重写例5,让代码具有更好的可读性:

#include <iostream>
using namespace std;

typedef int (*PFun)(int, int);

int add(int x, int y){  
	return x + y;
}
int substract(int x, int y){  
	return x - y;
}

// 定义一个名为calculateAndTransfer(int)的函数:在内部执行一次计算,并且把输入的函数指针再返回,传递下去
// 输入参数为函数指针(其类型为int (*pTemp)(int, int))和两个int变量
// 返回值为同样的函数指针pTemp(其类型为int (*pTemp)(int, int))
// 下面等价于:int (*calculateAndTransfer(int (*fun)(int, int), int x, int y))(int, int){ 
PFun calculateAndTransfer(PFun fun, int x, int y){ 
	cout << "fun(x,y) = " << fun(x,y) << endl;
	return add;
}

int main(){	
	PFun fp;
	fp = calculateAndTransfer(add,1,2); 
	cout << "1 + 2 = " << fp(1,2) << endl;
	fp = calculateAndTransfer(substract,5,1);  
	cout << "5 - 1 = " << fp(5,1) << endl;
	return 0;
}

输出:

fun(x,y) = 3
1 + 2 = 3
fun(x,y) = 4
5 - 1 = 6

函数指针的数组

定义一个由函数指针组成的数组:([]的优先级高于*,因此直接把(*fp)变为(*fp[3])即可

  • int (*fp[3])(int, int) : fp是一个数组,元素个数为3,每个元素是一个函数指针(指向int (*pf)(int, int)的类型)
  • int (*(fp[3])(int, int) : 与上面等价,fp是一个数组
  • int ((*fp)[3])(int, int) : (非法,编译会报错:```error: declaration of 'gp' as array of functions):fp是一个指针,指向一个数组,这个数组的元素个数必须为3,每个元素是一个函数,注意,是函数而不是函数指针,*符号给到fp头上了,因此,编译器会认为你要创建函数的数组,这是不允许的,只允许创建函数指针的数组。

例10:函数指针数组:

#include <iostream>
using namespace std;

typedef int (*PFun)(int, int); 

int add(int x, int y){
	return x + y;
}

int substract(int x, int y){
	return x - y;
}

int main(){	
	// fp是一个数组,元素个数为2,每个元素是一个函数指针(指向int (*pf)(int, int)的类型)
	int (*fp[2])(int, int);
	fp[0] = add;
	fp[1] = substract;
	cout << fp[0](5,3) << endl;
	cout << fp[1](5,3) << endl;
	
	// 下面会报错,从字面上理解:gp是一个指针,指向函数的数组,而函数的数组是非法的,函数指针的数组是允许的
	// int ((*gp)[2])(int, int);  \\ error: declaration of 'gp' as array of functions
	
	return 0;
}

输出:

8
2

类的成员函数(方法)的指针

与普通函数指针类似,类的静态/非静态成员函数(方法)指针也有声明、赋值、调用三个步骤:

普通函数 类的非静态成员函数
(类名为A,实例对象为a,对象指针为pa)
类的静态成员函数(类名为A)
函数声明 int fun(double x, double y); int A::fun(double x, double y); int A::static_fun(double, double);
函数指针的声明 int (*fp)(double, double); int (A::*fp2)(double x, double y); int (*fp3)(double, double);
函数指针的赋值 fp = fun; 或 fp = &fun; fp2 = A::fun;或 fp2 = &A::fun; fp3 = A::static_fun;
函数指针的调用 fp(x, y); 或 (*fp)(x, y); (a.*fp2)(x,y);
(pa->*fp2)(x,y);
fp3(x, y); 或 (*fp3)(x, y);

几个注意点:

  • 新引入三个运算符:声明::*, 调用.*->*
  • 声明时,只有类的非静态成员函数指针前才加类名。
  • 赋值时,函数指针前都不加类名,只有类的非静态成员函数指针的等号右侧的才加类名。
  • 调用时,只有类的非成员函数指针前要加对象名,因为必须通过this指针来决定调用的是哪个实例对象的函数。其中(a.*fp2)(x,y)和(pa->*fp2)(x,y)的小括号不能省略,因为.*->*的优先级低于()

总之,类的静态成员函数与普通函数非常类似,只有在赋值的时候需要等号右侧是类名::静态函数的形式,其他的语法完全一致。而类的非静态成员函数在声明时前面要加类名,赋值时等号右侧要加类名,调用时前面要加具体的对象名。

例11:比较普通函数、类的非静态成员函数、类的静态成员函数的声明、赋值和调用:

#include <iostream>
#include <string>
using namespace std;

class Mobile{
public:
	Mobile(string number):_number(number){}
	void from(string another_number){
		cout << _number << " is receiving a call from " << another_number << endl;
	}
	void to(string another_number){
		cout << _number << " is calling to " << another_number << endl;
	}
	static void printInfo(){
		cout << "Static function: Mobile works good!" << endl;
	}
private:
	string _number;
};

void fun(string number){
	cout << "Normal function: number " << number << endl;
}

int main(){	
	// 普通函数的指针: 
	void (*fp1)(string);  // 声明
	fp1 = fun;            // 赋值
	fp1("999");           // 调用
	(*fp1)("999");        // 调用的第二种等价方式
	
	// 类的非静态成员函数(方法)的指针:
	Mobile m("666888"), *mp = &m;  
	void (Mobile::*fp2)(string);   // 声明,使用 ::*  (小括号不能少:写成Mobile::*fp2(string)会报错)
	fp2 = Mobile::from;            // 赋值,也可以写成fp2 = &Mobile::from; 因为::优先级高于&
	(m.*fp2)("12345");             // 调用,不能写成 m.*fp2("12345") 因为.*的优先级低于()
	// (*(m.*fp2))("12345");       // 错误,调用没有像普通函数一样的第二种等价方式(前面加*)
	(mp->*fp2)("12345");           // 调用,不能写成 m->*fp2("12345") 因为->*的优先级低于()
	fp2 = Mobile::to;              // 赋值 
	(m.*fp2)("54321");             // 调用
	(mp->*fp2)("54321");           // 调用
	
	// 类的静态成员函数(方法)的指针:
	void (*fp3)(); 				// 声明: 同普通函数
	fp3 = Mobile::printInfo;    // 赋值:等号右侧用类名::静态函数,也可以写成fp3 = &Mobile::printInfo; 
	fp3();                      // 调用:同普通函数
	(*fp3)();                   // 调用的第二种等价方式:同普通函数
	
	return 0;
}

输出:

Normal function: number 999
Normal function: number 999
666888 is receiving a call from 12345
666888 is receiving a call from 12345
666888 is calling to 54321
666888 is calling to 54321
Static function: Mobile works good!
Static function: Mobile works good!

参考资料

标签:fp,return,函数,int,C++,详解,fun,函数指针
From: https://www.cnblogs.com/phyjack/p/18445368

相关文章

  • 在树莓派上安装c++版本的opencv并运行
     这里默认你用的是树莓派的镜像(因为ubantu对树莓派的性能占用有点大)树莓派安装使用opencvc++版本首先我们安装依赖sudoapt-getinstallbuild-essentialsudoapt-getinstallcmakelibgtk2.0-devpkg-configlibswscale-devsudoapt-getinstalllibjpeg-devlibpng......
  • C语言 函数指针
    概念在C语言中,函数指针是一种特殊的指针类型,它指向的是函数而不是普通的数据变量。函数在内存中有其入口地址,函数指针就是用来存储这个地址的变量。函数指针的定义函数指针的定义形式如下:返回值类型(*指针变量名)(参数类型列表);例如,定义一个指向返回值为int,参数为int......
  • C++指针等于地址加偏移量
    概述本文通过c++示例代码演示指针的加减法运算及对“指针=地址+偏移量”的理解。研究示例1.首先来检查各种变量类型所占的内存大小#include<iostream>usingnamespacestd;intmain(){ cout<<sizeof(char)<<endl;//1Byte cout<<sizeof(short)<<e......
  • 南沙C++信奥赛陈老师解一本通题 1966:【14NOIP普及组】比例简化
    ​ 【题目描述】在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有1498人,反对的有902人,那么赞同与反对的比例可以简单的记为1498:902。不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大......
  • 南沙C++信奥赛陈老师解一本通题 1820:【00NOIP提高组】进制转换
    ​ 【题目描述】我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式。例如,123可表示为1*10^2+2*10^1+3*10^0这样的形式。与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置......
  • Nuxt.js 应用中的 app:rendered 钩子详解
    title:Nuxt.js应用中的app:rendered钩子详解date:2024/10/2updated:2024/10/2author:cmdragonexcerpt:摘要:本文详细介绍了Nuxt.js应用程序中的app:rendered钩子,包括其定义、调用时机、上下文信息以及通过实际案例展示如何记录性能和发送日志到服务器。categories......
  • c++ vector容器、字符串
    c++vector容器          字符串:           ......
  • 红黑树操作图文详解,包学会
    RB-tree(红黑树)1、概要红黑树是一种自平衡的二叉搜索树,它在插入、删除和查找通过一定的规则可以把时间复杂度控制在O(logn)内。红黑树广泛应用域各种场景,如C++的map和set底层实现等。红黑树不仅是个二叉搜索树,而且必须满足以下性质:每个节点不是红色就是黑色根节点为黑......
  • 最长上升子序列LIS 详解+变形+拓展
    最长上升子序列(LIS):定义:最长上升子序列(LIS)是一个序列中,找到一个子序列,使得这个子序列的元素是严格递增的,且该子序列的长度最大*子串和子序列的差别:子串: 元素的连续性,必须是相邻的子序列:元素的相对顺序,可以不连续 从实例中来[1,7,5,6,9,2,4]这个数组根据肉眼......
  • OpenAi FunctionCalling 案例详解
    源码详细讲解pdf及教学视频下载链接:点击这里下载FunctionCalling的单一函数调用天气预报查询(今天长沙的天气如何?)1importjson2importrequests3fromopenaiimportOpenAI45client=OpenAI()67location="长沙"89defget_current_weather(c......