无法将参数:_cdecl*转换为_thiscall*解决办法

  • 敲黑板重点!!
  • 一,原来的编译报错的代码
  • 二,编译报错:无法将参数:void(_cdecl*)(int*,int)转换为void(_thiscall*)(Qsort::⭐)(int*,int))
    • 报错无法从void (_cdecl*)(int*,int)到void (_thiscall*)(int*,int)原因分析:
  • 三,解决办法:
  • 四,_thiscall与_cdecl
  • 五,函数指针的声明
    • (Ⅰ)_cdecl函数指针的声明:
    • (Ⅱ)_thiscall函数指针的声明
    • (Ⅲ)这样混合赋值就会编译报错
    • (Ⅳ)成员函数指针的语法小细节
  • 六,写在最后-总结
  • 七,更多函数指针的细节

敲黑板重点!!

(Ⅰ)普通的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;
}

二,编译报错:无法将参数:void(_cdecl*)(int*,int)转换为void(_thiscall*)(Qsort::⭐)(int*,int))

无法将参数:_cdecl*转换为_thiscall*解决办法_第1张图片

报错无法从void (_cdecl*)(int*,int)到void (_thiscall*)(int*,int)原因分析:

我头文件声明public的static void qsort(int*,int),是一个静态的类函数,可以脱离于对象而存在
然后这种函数就是以 " _cdecl " 的方式进行编译(普通C函数那样编译)

然而,我的sort函数第三个却声明了一个成员函数指针类型的形参,以"_thiscall"方式编译
实参从_cdecl到_thiscall转换失败,因为这种转换本身就非常离谱!!因此编译器马上给你这个编译错误!!

三,解决办法:

就是直接使得他们函数指针类型匹配就行,
_cdecl的函数指针就传到_cdecl的形参里面,默认的C函数调用方式就是直接用。
_thiscall的函数指针就传到_thiscall的形参里面,再以对象调用的方式来调用这个函数。

不要以不同类型的编译方式传参就行,传相同类型的函数指针即可。
下面是我以"_thiscall"方式来调用该函数(稍微改了一下之前的代码)

无法将参数:_cdecl*转换为_thiscall*解决办法_第2张图片

四,_thiscall与_cdecl

_cdecl是C语言默认的函数调用方式,更详细的参见百度百科的_cdecl解释。
_thiscall就是对象调用函数的方式,函数参数从右往左入栈,最后编译时增加一个形参,传入一个this指针

五,函数指针的声明

(Ⅰ)_cdecl函数指针的声明:

下面把一个普通的函数赋值给普通函数指针,完全没问题

void print(){
     
	std::cout<<"HelloWorld!!\n";
}
void (*f)()=&print;//普通函数指针的初始化,_cdecl方式编译

(Ⅱ)_thiscall函数指针的声明

把一个实例对象的一个函数名赋值给一个成员函数指针,完全没有问题

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)();
}

输出结果就是Hello\n
无法将参数:_cdecl*转换为_thiscall*解决办法_第3张图片

(Ⅲ)这样混合赋值就会编译报错

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页,

你可能感兴趣的:(C++学习笔记,c++语法错误,c++)