指向 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;
                }
            }

函数指针需要是静态的(不能是对象方法)。 所以在上面的示例中,您可以将 gcdsimplification 声明为标准函数(不是对象方法)。

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.

的语法

最后说明: 在这里使用回调看起来像是严重的过度工程,但我想可能存在对它的需求,因为为了简化示例代码而删除了细节。