c++ 指向 non-static 成员函数的指针
c++ pointer to non-static member functions
我已经阅读了很多关于指向 non-static 成员函数的帖子和答案,但是 none 看起来能够解决我的问题。
所以我创建了一个简短的例子来复制我的问题:即使这个例子可以用不同的方式 "solved",对于最终的软件来说,保持例子中的结构很重要,谢谢。
这是 class "Funcs.h" 的 header:
class Funcs
{
private:
double a = 1, b = 2;
public:
Funcs();
~Funcs();
double Fun1(double X);
double solver(double X0);
double aaa(double(*fun)(double), double x0);
};
这是 class "Funcs.cpp":
的 cpp
#include "Funcs.h"
using namespace std;
Funcs::Funcs()
{
}
Funcs::~Funcs()
{
}
double Funcs::Fun1(double X) {
double f1 = a*X;
return f1;
}
double Funcs::solver(double X0)
{
double result;
result = aaa(Fun1, X0);
return result;
}
double Funcs::aaa(double(*fun)(double), double x0)
{
return fun(x0);
}
最后这是主要的 "main.cpp":
#include <iostream>
#include "Funcs.h"
using namespace std;
int main() {
double x0=1;
double result;
Funcs funcs;
result = funcs.solver(x0);
cout << result << endl;
return 0;
}
当我调用 "result = aaa(Fun1, X0);" 时,错误出在方法 Funcs::solver 中,因为我不能使用指向 Fun1 的指针,因为它是 non-static 成员。同时我也不能让它静态化,否则在静态方法里面是看不到变量"a"的。
在此先感谢您的帮助。
问题是您试图传递一个指向成员函数的指针,而期望传递一个指向非成员函数或静态成员函数的指针。这些是不同的类型。
这里"fun"是一个指向函数的指针:double(*fun)(double)
.
这里是指向 class 函数的成员函数的指针:double(Funcs::*fun)(double)
下面是修改代码以使其正常工作的方法。
class Funcs
{
// all the rest is the same
double aaa(double(Funcs::*fun)(double), double x0);
};
double Funcs::solver(double X0)
{
// ...
result = aaa(&Funcs::Fun1, X0);
// ...
}
double Funcs::aaa(double(Funcs::*fun)(double), double x0)
{
return (this->*fun)(x0);
}
查看实例 at Coliru。
如果您想有意限制您的方法 aaa
仅接受 Funcs
个成员函数作为 fun
,这可能是一个很好的方法。如果您还想传递非成员函数或例如aaa
的 lambda,请考虑改用 std::function
。
您的问题是指向函数的指针与指向成员函数的指针不同。阅读 this for more info and this 了解编写指向成员函数的指针的简洁方法。如果您需要保留此结构,请将 aaa 设为静态或非成员函数,将其所需的所有内容作为参数,或者将 aaa 的第一个参数更改为采用 double(Funcs::*)(double)
而不是 double(*fun)(double)
。您甚至可以重载 aaa 以支持这两种用途。
实际上 Funcs::Fun1
不是 double(*)(double)
。
任何非静态方法都具有此签名:return_type(*)(class_type* this, arguments...)
让我们看看确切的类型:
//first argument of `aaa` has type double(*)(double)
double aaa(double(*fun)(double), double x0);
double Funcs::Fun1(double X) {
double f1 = a*X;
return f1;
}
// Fun1 has type double(Funs::*)(double)
// i.e it's a method of Funs and it takes (implicitly) first argument
// which is `this` pointer
// so that how `aaa` must look like
double aaa(double(Funs::*fun)(double), double x0)
{
// special sytax
*this.*fun(x0);
}
// and that how `solver` looks like
double Funcs::solver(double X0)
{
double result;
// get pointer to method
result = aaa(&Funs::Fun1, X0);
return result;
}
如果您不熟悉指向方法的指针 - 请查看 this
我对 c++ 还是个新手,但我知道的解决方案是让一个静态函数充当委托。 https://docs.microsoft.com/ru-ru/windows/win32/learnwin32/managing-application-state-
///按照 LINK 的完整代码来理解我在说什么 :)
看看 win32 API 如何提供静态回调函数作为委托。简而言之,函数接受多个输入,最后一个参数是调用者作为空指针传递的 class。
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
// routine to recast back pointer to your class type so you have access to your local members with "This"
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
pThis->m_hwnd = hwnd;
}
看看 lParam 是如何被转换回 DERIVED_TYPE 的,这是你的 class 的一种类型,pThis 的行为与正常情况一样,让你可以访问 class 成员.
我已经阅读了很多关于指向 non-static 成员函数的帖子和答案,但是 none 看起来能够解决我的问题。
所以我创建了一个简短的例子来复制我的问题:即使这个例子可以用不同的方式 "solved",对于最终的软件来说,保持例子中的结构很重要,谢谢。
这是 class "Funcs.h" 的 header:
class Funcs
{
private:
double a = 1, b = 2;
public:
Funcs();
~Funcs();
double Fun1(double X);
double solver(double X0);
double aaa(double(*fun)(double), double x0);
};
这是 class "Funcs.cpp":
的 cpp#include "Funcs.h"
using namespace std;
Funcs::Funcs()
{
}
Funcs::~Funcs()
{
}
double Funcs::Fun1(double X) {
double f1 = a*X;
return f1;
}
double Funcs::solver(double X0)
{
double result;
result = aaa(Fun1, X0);
return result;
}
double Funcs::aaa(double(*fun)(double), double x0)
{
return fun(x0);
}
最后这是主要的 "main.cpp":
#include <iostream>
#include "Funcs.h"
using namespace std;
int main() {
double x0=1;
double result;
Funcs funcs;
result = funcs.solver(x0);
cout << result << endl;
return 0;
}
当我调用 "result = aaa(Fun1, X0);" 时,错误出在方法 Funcs::solver 中,因为我不能使用指向 Fun1 的指针,因为它是 non-static 成员。同时我也不能让它静态化,否则在静态方法里面是看不到变量"a"的。
在此先感谢您的帮助。
问题是您试图传递一个指向成员函数的指针,而期望传递一个指向非成员函数或静态成员函数的指针。这些是不同的类型。
这里"fun"是一个指向函数的指针:double(*fun)(double)
.
这里是指向 class 函数的成员函数的指针:double(Funcs::*fun)(double)
下面是修改代码以使其正常工作的方法。
class Funcs
{
// all the rest is the same
double aaa(double(Funcs::*fun)(double), double x0);
};
double Funcs::solver(double X0)
{
// ...
result = aaa(&Funcs::Fun1, X0);
// ...
}
double Funcs::aaa(double(Funcs::*fun)(double), double x0)
{
return (this->*fun)(x0);
}
查看实例 at Coliru。
如果您想有意限制您的方法 aaa
仅接受 Funcs
个成员函数作为 fun
,这可能是一个很好的方法。如果您还想传递非成员函数或例如aaa
的 lambda,请考虑改用 std::function
。
您的问题是指向函数的指针与指向成员函数的指针不同。阅读 this for more info and this 了解编写指向成员函数的指针的简洁方法。如果您需要保留此结构,请将 aaa 设为静态或非成员函数,将其所需的所有内容作为参数,或者将 aaa 的第一个参数更改为采用 double(Funcs::*)(double)
而不是 double(*fun)(double)
。您甚至可以重载 aaa 以支持这两种用途。
实际上 Funcs::Fun1
不是 double(*)(double)
。
任何非静态方法都具有此签名:return_type(*)(class_type* this, arguments...)
让我们看看确切的类型:
//first argument of `aaa` has type double(*)(double)
double aaa(double(*fun)(double), double x0);
double Funcs::Fun1(double X) {
double f1 = a*X;
return f1;
}
// Fun1 has type double(Funs::*)(double)
// i.e it's a method of Funs and it takes (implicitly) first argument
// which is `this` pointer
// so that how `aaa` must look like
double aaa(double(Funs::*fun)(double), double x0)
{
// special sytax
*this.*fun(x0);
}
// and that how `solver` looks like
double Funcs::solver(double X0)
{
double result;
// get pointer to method
result = aaa(&Funs::Fun1, X0);
return result;
}
如果您不熟悉指向方法的指针 - 请查看 this
我对 c++ 还是个新手,但我知道的解决方案是让一个静态函数充当委托。 https://docs.microsoft.com/ru-ru/windows/win32/learnwin32/managing-application-state-
///按照 LINK 的完整代码来理解我在说什么 :)
看看 win32 API 如何提供静态回调函数作为委托。简而言之,函数接受多个输入,最后一个参数是调用者作为空指针传递的 class。
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
// routine to recast back pointer to your class type so you have access to your local members with "This"
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
pThis->m_hwnd = hwnd;
}
看看 lParam 是如何被转换回 DERIVED_TYPE 的,这是你的 class 的一种类型,pThis 的行为与正常情况一样,让你可以访问 class 成员.