将成员函数传递给另一个对象的成员函数 C++

3

我在尝试将一个函数作为另一个对象的函数参数传递时遇到了问题。我知道有很多类似的话题,但是要么无法使它们的解决方案起作用,要么无法理解它们。

class foo
{
public:
    void func1(void (*Drawing)(void));

    template<class T>
    void func2(void (T::*Drawing)(void));
};

class bar
{
private:
    foo myFoo;
    void Drawing();
    void func3() {
        // Attempt 1
        myFoo.func1(Drawing);

        // Attempt 2
        myFoo.func2<bar>(&bar::Drawing);
    }
};

我的第一次尝试中,出现了错误,无法将void (bar::*)(void)转换为void (*)(void),后来我发现有普通函数指针和成员函数指针的区别。
我的第二次尝试是为了克服这个问题,但现在出现了未解决的外部引用错误...
那么我如何成功地将我的Drawing()成员函数从另一个对象传递到另一个函数中去呢?

2
使用函数对象,而不是函数指针。 - The Vivandiere
5
你会出现未解决的符号错误,因为你没有提供“func2”的定义。 - Captain Obvlious
2
你能发布完整的链接器错误消息吗? - The Vivandiere
我不明白在foo中如何使用&bar::Drawing,因为它是一个私有成员函数。即使给出成员指针,编译器也不允许你调用它。无论如何,你都需要一个实例来调用它,所以你需要将*this传递给该函数。 - Austin Mullins
1
@AustinMullins 它在 bar 中是可用的,访问控制只保护名称。而且它在 foo::func2 中有不同的名称。想象一下如果它像你描述的那样工作 - 你甚至不能返回私有成员变量的引用。 - milleniumbug
显示剩余3条评论
2个回答

5
问题在于你不能将 bar::Drawing 视为一个void (*)(void)函数,因为它是一个非静态方法,因此需要一个对象(将使用该this上下文)。
一种解决方案,假设您可以使用c++11,则是使用std::bind并稍微修改您的foo定义:
class foo
{
    public:
    void func1(std::function<void(void)> Drawing)
    {
        Drawing(); // or do whatever you want with it
    }
};

那么您将能够做到:
void bar::func3() {
    myFoo.func1(std::bind(&bar::Drawing, this));
}

让许多潜在用途成为可能。
int main()
{
    bar myBar;
    myBar.func3();

    foo myFoo;
    myFoo.func1([](){ printf("test\n"); });
    return 0;
}

这个可行!非常感谢。 如果我没有使用C++11,还有其他方法可以解决这个问题吗? - Enriel

1

我猜测您忽略了一些关键细节,以至于无法了解您试图实现的目标。不过,以下内容应该能够给您提供一些需要做的事情的思路。

代码

#include <iostream>

class foo
{
public:
    void func1(void (*Drawing)(void))
    {
        std::cout << "func1\n";
    }

    template<class T>
    void func2(T* instance, void (T::*fn)(void))
    {
        std::cout << "func2: ";
        (instance->*fn)();
    }
};

class bar
{
public:
    bar()
    {
        func3();
    }

private:
    foo myFoo;

    void Drawing()
    {
        std::cout << "bar::Drawing()\n";
    }

    void func3()
    {
        // Attempt 1
        //myFoo.func1(Drawing); // This won't work

        // Attempt 2
        myFoo.func2(this, &bar::Drawing); // Must pass an object instance if you plan to use the member function
    }
};

int main(int argc, char *argv[])
{
    bar b;

    return 0;
}

样例输出

func2: bar::Drawing()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接