将类的成员函数传递给类外的参数

时间:2014-11-29 04:04:03

标签: c++ member-function-pointers

如何将类的成员函数作为参数传递给另一个类的另一个成员函数?

class theSecondClass
{
    public:
    void theFunctionReceiver(void (theFirstClass::*Function)(void));
    {
         // This part is wrong. "Operand of * must be a pointer"
         (*Function)(); 
    }
}

class theFirstClass
{
    public:
    theSecondClass * SecondClassInstance;
    void theFunctiontoPass(void)
    {
        printf("It worked \n");
        return;
    }
    void theFunctiontoCall(void)
    {
        SecondClassInstance->theFunctionReceiver(theFunctiontoPass);
    }
};

假设theSecondClasstheFirstClass都已经制作完成。我从某个地方打电话给theFirstClass->theFunctiontoCall()

我不明白。当我把它传入时,它是否作为指针传入?

我已经看过几个类似的线程,但我完全不了解它们。 我使用VS 2013,基本编译器。

1 个答案:

答案 0 :(得分:1)

撰写本声明时:

SecondClassInstance->theFunctionReceiver(theFunctiontoPass);

你的意思是:

SecondClassInstance->theFunctionReceiver(&theFunctiontoPass);

哪个应该给你一个编译器警告它是一个不合格的成员引用,这会指出你实际写的是:

SecondClassInstance->theFunctionReceiver(&theFirstClass::theFunctiontoPass);

您正在获取指向类定义上的成员函数的指针。 “this”不是隐含的或包含在包中。如果它是静态的,那么你可以在没有类实例的情况下调用的唯一方法。 (在这种情况下,它不会作为成员函数进行类型检查......它只是一个普通的函数指针。)

  

如果我要传递对我的类的引用,为什么我甚至需要传递它的功能?我无法在链接的情况下调用它,ButtonObj-> Buttonfunc();

使用指向成员函数的指针的唯一原因是获得某种抽象,其中一段代码可以调用它不需要显式命名的成员函数。如果您对theSecondClass::theFunctionReceiver知道theFirstClass::theFunctionToPass的名称和theFirstClass的标识感到满意......那么请确保只需传递对第一类实例的引用并明确调用该方法。

可能想要theSecondClass将调用theFirstClass上具有匹配签名的多个成员函数中的任何一个的情况......它只是没有想要硬编码哪一个。在这种情况下,然后传递一对类引用和成员函数。你似乎怀疑这种情况并不常见,因此你会说得对。每年我都要回头查看如何在类上调用指向成员的语法,因为除了StackOverflow问题之外它几乎不会出现:

How to call through a member function pointer?

更有可能你想要的东西(以及人们问那些SO问题实际上想要的东西)是分开关注点,以便theSecondClass有一个钩子来执行某些东西,但不需要完全了解theFirstClass。查看 lambdas std :: function std :: bind ,了解您可能能够满意地进行实验的广义解决方案。

这是一个示例,向您展示将抽象调用方式自动封装到std :: function中的样子。它在现场创建一个函数对象,捕获封闭的this指针,以便在调用它时调用对象上的方法:

#include <iostream>
#include <functional>

class theSecondClass {
public:
    void theFunctionReceiver(std::function<void()> const & Function) {
         Function(); 
    }
};

class theFirstClass {
private:
    theSecondClass * SecondClassInstance;
public:
    void theFunctiontoPass() {
        std::cout << "It worked\n";
    }
    void theFirstClass::theFunctiontoCall() {
        SecondClassInstance->theFunctionReceiver(
            [this]() {theFunctiontoPass();}
        );
    }
};

int main() {
    theFirstClass tfc;
    tfc.theFunctiontoCall();
}

请注意,这是C ++ 11,如果你还没有,我建议使用它。但是,C ++ 98中存在不太方便的符号和机制。

这可以纠正您的代码问题,这些问题超出了您提到的问题。请评论撰写Minimal, Complete, Verifiable Example。应该可以将提供的代码粘贴到编译器中,并且只看 您想要讨论的错误。

  • 这会在类定义结束后添加分号
  • 当您在类
  • 中提供实体时,这将删除方法声明后的分号
  • 您需要各种正向定义才能使其正常工作,这不需要它们
  • 当函数不带参数时,习惯上将void foo()定义为void foo(void)return;作为函数的最后一行,不返回任何值也是多余的。
  • 避免使用printf learn iostreams
  • 编写新的C ++代码
  • 将成员变量偏向私有或受保护。
  • 在StackOverflow代码示例中尝试保持简短,不需要滚动条;最好不要给开口括号(大部分时间)

虽然命名是主观的,但我建议给出你的班级名称初始上限比给出变量初始上限更好。