函数调用方式引起的编译错误

1 问题引入

在使用函数模板时有如下定义

template

void StartThread(xClass* pThis, xReturn (xClass::* pfn)())

{

  return;

}

在基于对话框的程序中使用该函数模板

BOOL CMyDlg::OnInitDialog()

{

StartThread(this, ThreadAccept);

}

ThreadAccept()函数是CMyDlg的成员函数,定义如下

DWORD CMyDlg::ThreadAccept()

{

  return 0;

}

此时,编译报错信息为

error C3867: CMyDlg::ThreadAccept函数缺少参数列表”。

2 问题分析

主要问题出在函数调用方式上。在CMyDlg::OnInitDialog()函数中,使用_cdecl的方式直接调用ThreadAccept();在函数模板中定义的StartThread()函数的第二个参数是xClass::*,表示类的成员函数的指针,而类成员函数的调用方法是__thiscall。也就是说StartThread()函数的第二个参数要求函数是__thiscall调用方式,而在代码中将StartThread()函数的第二个参数指定为_cdecl方式,因此调试时报错。

3 问题解决

将调用StartThread()函数的代码修改为

StartThread(this, &CMyDlg::ThreadAccept);

StartThread()函数的第二个参数设置类成员函数,即将调用方式改为__thiscall

4 问题扩展

4.1 函数指针

函数指针是指向函数而非指向对象的指针。像其它指针一样,函数指针也指向某个特定的类型。函数类型由其返回类型以及形参表确定,而与函数名无关。例如:

bool (*pf)(const int&, const int&);

以上语句将pf声明为指向函数的指针,它所指向的函数带有两个const int&类型的形参和bool类型的返回值。

类成员函数指针的定义与上述代码类似

bool (CMyClass::* pf)(const int&, const int&)

以上代码定义了CMyClass类的成员函数的指针。

4.2 函数调用方式

函数常见的调用方式有_cdecl_stdcall__thiscall等。

_stdcall调用方式一般用于Win32 API函数中。函数采用从右向左的压栈方式,由函数本身在退出时清空堆栈;_cdecl调用方法是CC++函数的默认调用方式。函数采用从右向左的压栈方式,由该函数的调用者来清空堆栈;__thiscall调用方式用在类的成员函数中,函数采用从右向左的压栈方式,在Visual C++2005之前的版本汇总,由于__thiscall不是关键字,程序无法显式指定thiscall调用方式。

你可能感兴趣的:(C++基础)