指向 class 方法调用的指针
Pointer to a class method call
我正在尝试定义一个名为 RationalNumber
的 class。在构造函数中,我想使用回调函数将 RationalNumber
表示的分数简化为另一个函数(名为 simplification
),但我收到一些错误,我无法弄清楚我遗漏了什么。
第一个错误是cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
#pragma once
#include <iostream>
using namespace std;
class RationalNumber {
typedef void (RationalNumber::*pointer_to_f)(RationalNumber&);
private:
int a;
int b;
void callback(pointer_to_f);
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
pointer_to_f p = &simplification; // <-- line 21, location of the first error
callback((p)(this));
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) ) {
(*p)(x);
}
完整的错误日志:
Error C2440 'initializing': cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error C2511 'void RationalNumber::callback(RationalNumber::pointer_to_f *(__cdecl *)(RationalNumber &))': overloaded member function not found in 'RationalNumber' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error C2065 'x': undeclared identifier Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error (active) E0144 a value of type "void (*)(RationalNumber &x)" cannot be used to initialize an entity of type "RationalNumber::pointer_to_f" Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error (active) E0147 declaration is incompatible with "void RationalNumber::callback(RationalNumber::pointer_to_f)" (declared at line 11 of "...\source\repos\Prob2\Prob2\NumarRational.h") Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error (active) E0109 expression preceding parentheses of apparent call must have (pointer-to-) function type Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 22
Error (active) E0020 identifier "x" is undefined Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error C2064 term does not evaluate to a function taking 1 arguments Prob2 ....source\repos\Prob2\Prob2\NumarRational.h 22
谢谢!
下面修改后的代码编译并显示了如何将静态方法用作 "callback" 但如上所述,它不清楚为什么您不想直接使用构造函数中的 simplification
方法(而不是使用此方法的指针)
#include <functional>
class RationalNumber {
private:
int a;
int b;
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
std::function<void(RationalNumber&)> p= &RationalNumber::simplification;
p(*this) ;
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
函数指针需要是静态的(不能是对象方法)。
所以在上面的示例中,您可以将 gcd
和 simplification
声明为标准函数(不是对象方法)。
cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f'
上线
pointer_to_f p = &simplification;
让我们看看这里有什么。此行初始化类型为 RationalNumber::pointer_to_f
的变量 (p
),它对应于尝试转换的目标。 =
右边是RationalNumber::simplification
的地址,是RationalNumber&
到void
的静态成员函数。检查,与错误消息匹配。
所以第一个错误归结为 pointer to member function 必须指向非静态成员函数这一事实。静态成员函数的地址是一个普通的函数指针(主要是因为它缺少隐藏的 this
参数)。
鉴于您的设置,从 simplification
中删除 static
关键字及其参数似乎是有意义的。让它在 *this
上运行,一旦成员函数不再是 static
.
,它就可用
或者,如果出于某种原因 simplification
需要 static
,您可以将指向成员函数的指针更改为指向函数的常规指针。 (鉴于函数在任何一种情况下都需要一个 RationalNumber
对象,我不明白为什么 static
是可取的。)
其余错误在技术上是独立的,但我会抛出一些与无效使用指向成员函数的指针有关的错误。
callback((p)(this));
这将调用 p
指向的函数并提供指针 this
作为参数。返回值 (void
) 成为 callback
的参数。如果要将 p
作为参数传递给 callback
,则传递 p
:
callback(p);
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) )
这与声明不符。您将 callback
声明为参数为 pointer_to_f
的函数。这个定义有一个参数,其类型是一个接受 RationalNumber&
参数并返回 pointer_to_f
的函数(x
在这里没有意义)。保持一致!
void RationalNumber::callback(pointer_to_f p)
如果你想在调用 p
时传递一些东西作为参数,你需要第二个参数。另请参阅 Function pointer to member function 以了解如何修复用于调用 p
.
的语法
最后说明: 在这里使用回调看起来像是严重的过度工程,但我想可能存在对它的需求,因为为了简化示例代码而删除了细节。
我正在尝试定义一个名为 RationalNumber
的 class。在构造函数中,我想使用回调函数将 RationalNumber
表示的分数简化为另一个函数(名为 simplification
),但我收到一些错误,我无法弄清楚我遗漏了什么。
第一个错误是cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
#pragma once
#include <iostream>
using namespace std;
class RationalNumber {
typedef void (RationalNumber::*pointer_to_f)(RationalNumber&);
private:
int a;
int b;
void callback(pointer_to_f);
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
pointer_to_f p = &simplification; // <-- line 21, location of the first error
callback((p)(this));
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) ) {
(*p)(x);
}
完整的错误日志:
Error C2440 'initializing': cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error C2511 'void RationalNumber::callback(RationalNumber::pointer_to_f *(__cdecl *)(RationalNumber &))': overloaded member function not found in 'RationalNumber' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error C2065 'x': undeclared identifier Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error (active) E0144 a value of type "void (*)(RationalNumber &x)" cannot be used to initialize an entity of type "RationalNumber::pointer_to_f" Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error (active) E0147 declaration is incompatible with "void RationalNumber::callback(RationalNumber::pointer_to_f)" (declared at line 11 of "...\source\repos\Prob2\Prob2\NumarRational.h") Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error (active) E0109 expression preceding parentheses of apparent call must have (pointer-to-) function type Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 22
Error (active) E0020 identifier "x" is undefined Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error C2064 term does not evaluate to a function taking 1 arguments Prob2 ....source\repos\Prob2\Prob2\NumarRational.h 22
谢谢!
下面修改后的代码编译并显示了如何将静态方法用作 "callback" 但如上所述,它不清楚为什么您不想直接使用构造函数中的 simplification
方法(而不是使用此方法的指针)
#include <functional>
class RationalNumber {
private:
int a;
int b;
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
std::function<void(RationalNumber&)> p= &RationalNumber::simplification;
p(*this) ;
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
函数指针需要是静态的(不能是对象方法)。
所以在上面的示例中,您可以将 gcd
和 simplification
声明为标准函数(不是对象方法)。
cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f'
上线
pointer_to_f p = &simplification;
让我们看看这里有什么。此行初始化类型为 RationalNumber::pointer_to_f
的变量 (p
),它对应于尝试转换的目标。 =
右边是RationalNumber::simplification
的地址,是RationalNumber&
到void
的静态成员函数。检查,与错误消息匹配。
所以第一个错误归结为 pointer to member function 必须指向非静态成员函数这一事实。静态成员函数的地址是一个普通的函数指针(主要是因为它缺少隐藏的 this
参数)。
鉴于您的设置,从 simplification
中删除 static
关键字及其参数似乎是有意义的。让它在 *this
上运行,一旦成员函数不再是 static
.
或者,如果出于某种原因 simplification
需要 static
,您可以将指向成员函数的指针更改为指向函数的常规指针。 (鉴于函数在任何一种情况下都需要一个 RationalNumber
对象,我不明白为什么 static
是可取的。)
其余错误在技术上是独立的,但我会抛出一些与无效使用指向成员函数的指针有关的错误。
callback((p)(this));
这将调用 p
指向的函数并提供指针 this
作为参数。返回值 (void
) 成为 callback
的参数。如果要将 p
作为参数传递给 callback
,则传递 p
:
callback(p);
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) )
这与声明不符。您将 callback
声明为参数为 pointer_to_f
的函数。这个定义有一个参数,其类型是一个接受 RationalNumber&
参数并返回 pointer_to_f
的函数(x
在这里没有意义)。保持一致!
void RationalNumber::callback(pointer_to_f p)
如果你想在调用 p
时传递一些东西作为参数,你需要第二个参数。另请参阅 Function pointer to member function 以了解如何修复用于调用 p
.
最后说明: 在这里使用回调看起来像是严重的过度工程,但我想可能存在对它的需求,因为为了简化示例代码而删除了细节。