指向类方法调用的指针

问题描述 投票:0回答:1

我正在尝试定义一个名为 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  

谢谢你!

c++ class pointers methods call
1个回答
0
投票

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.


最后说明一下。 在这里使用回调看起来像严重的过度工程,但我想它的必要性可能存在于细节上,为了使示例代码简单,删除了它。


-1
投票

这段修改后的代码在编译时展示了如何使用静态方法作为 "回调",但正如上面所说,它并不清楚为什么你不想直接使用 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 作为标准函数(不是对象方法)。

© www.soinside.com 2019 - 2024. All rights reserved.