(Ⅰ)普通的C函数和类中的static函数以_cdecl方式编译,这种方式编译属于普通函数指针
(Ⅱ)类中的成员函数(非static)以_thiscall方式编译,这种编译方式属于成员函数指针
(Ⅲ)这两种函数指针不能由编译器自动转换,(好比你short间接转换成为int允许,但是double到char*就是不行),而且是不能互相自动转换的
(Ⅳ)成员函数指针只能赋值给成员函数指针,普通函数指针只能赋值给普通函数指针
“C++成员函数指针”和“普通函数指针” 具体的语法区别可以直接到目录的"五"那里看。
这是我快排的一段程序,所有函数都是static,无关的函数体我直接删掉了,最主要就是看主函数的那里就行
排序函数声明
#pragma once
#include
using std::swap;
class Qsort {
public:
static void qsort(int* a, int n) {
qsort(a, 0, n - 1);
}
};
主函数
#include
#include
#include
#include "Sort.h"
const int MAX = 1000;
int* q = new int[MAX];
void sort(int* a, int n, void(Qsort::* pf)(int*, int)) {
pf(a, n);//以_thiscall方式编译的函数指针不能直接调用,因此这行也会编译报错,需要对象调用才行!!!
}
void random(int* a, int n) {
srand(time(NULL));
for (int i = 0; i < n; i++) {
*a++ = rand();
}
}
int main()
{
random(q, MAX);
void (*pf)(int*, int) = Qsort::qsort;
sort(q, MAX, pf);
for (int i = 0; i < 100; i++) {
std::cout << q[i] << "\n";
}
delete[] q;
}
我头文件声明public的static void qsort(int*,int),是一个静态的类函数,可以脱离于对象而存在
然后这种函数就是以 " _cdecl " 的方式进行编译(普通C函数那样编译)
然而,我的sort函数第三个却声明了一个成员函数指针类型的形参,以"_thiscall"方式编译
实参从_cdecl到_thiscall转换失败,因为这种转换本身就非常离谱!!因此编译器马上给你这个编译错误!!
就是直接使得他们函数指针类型匹配就行,
_cdecl的函数指针就传到_cdecl的形参里面,默认的C函数调用方式就是直接用。
_thiscall的函数指针就传到_thiscall的形参里面,再以对象调用的方式来调用这个函数。
不要以不同类型的编译方式传参就行,传相同类型的函数指针即可。
下面是我以"_thiscall"方式来调用该函数(稍微改了一下之前的代码)
_cdecl是C语言默认的函数调用方式,更详细的参见百度百科的_cdecl解释。
_thiscall就是对象调用函数的方式,函数参数从右往左入栈,最后编译时增加一个形参,传入一个this指针
下面把一个普通的函数赋值给普通函数指针,完全没问题
void print(){
std::cout<<"HelloWorld!!\n";
}
void (*f)()=&print;//普通函数指针的初始化,_cdecl方式编译
把一个实例对象的一个函数名赋值给一个成员函数指针,完全没有问题
void print(){
std::cout<<"HelloWorld!!\n";
}
class Foo{
public:
void fun(){
std::cout<<"Hello\n";}
}
int main(){
void (Foo::*pf)()=Foo::fun;//普通函数指针声明前加上 "类名::" 就是成员函数指针的声明了,_thiscall 方式编译
Foo* pObj=new Foo;
(pObj->*pf)();
}
class Foo{
public:
static void f_1(){
}
void f_2(){
}
}
int main(){
void (*pf_1)()=&Foo::f_2;//实例的函数赋值给普通函数指针,不同类型的函数指针不能互相赋值,必然编译报错
void (Foo::*pf_2)()=&Foo::f_1;//把静态的函数赋值给成员函数指针,不同类型的函数指针不能互相赋值,必然报错
}
另外要注意:成员函数指针初始化的时候必须要强制用==&类名::函数名称==来初始化
函数调用无非就是
①对象调用,(_thiscall)
②指针/引用指向了一个对象,通过指针/引用来解引用或者直接用引用来调用函数(_thiscall),跟①完全一致,可以归纳到①里面去
③直接调用函数(_cdecl),默认的C方式调用函数,如果在类里面static了函数,那么也是_cdecl编译
函数指针就这几种类型,区分开就好
可以去看看《深度探索C++对象模型》P174页,