我正在尝试定义一个名为 RationalNumber
. 在构造函数中,我想简化用 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
谢谢你!
cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f'
在这一行
pointer_to_f p = &simplification;
让我们看看这里有什么。这一行初始化了一个变量(p
)类型的 RationalNumber::pointer_to_f
,这与试图转换的内容相对应。在右侧的 =
的地址。RationalNumber::simplification
的一个静态成员函数。RationalNumber&
到 void
. 检查,符合错误信息。
所以第一个错误归结为一个事实,即 成员函数指针 必须指向一个非静态成员函数。静态成员函数的地址是一个普通的函数指针(主要是因为它缺少隐藏的 this
参数)。)
考虑到你的设置,似乎应该删除 static
关键词从 simplification
以及删除其参数。让它在 *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
被调用时,你将需要第二个参数。也请参见 成员函数的函数指针 来了解如何修正你用来调用 p
.
最后说明一下。 在这里使用回调看起来像严重的过度工程,但我想它的必要性可能存在于细节上,为了使示例代码简单,删除了它。
这段修改后的代码在编译时展示了如何使用静态方法作为 "回调",但正如上面所说,它并不清楚为什么你不想直接使用 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
作为标准函数(不是对象方法)。