C++指向未知类的成员函数指针

3

免责声明我不使用BOOST或其他库

最后我学会了如何使用PointerToMemberFunction。这是我的示例代码

#include <iostream>

using namespace std;

class Foo
{
        public:
                void foo ( )
                {
                        cout << "I'm a foo method\n";
                };
};

class Bar
{
        public:
                void bar ( Foo* fooPtr , void(Foo::*fooFnPtr)() )
                {
                        (fooPtr->*fooFnPtr)();
                };
};

int main()
{
        Foo* foo = new Foo();
        Bar* bar = new Bar();

        bar->bar ( foo , &Foo::foo );

        return 0;
}

现在问题是,必须以某种方式修改Bar::bar,因为在实际项目中,它不知道fooFnPtr类指针指向哪个类。换句话说,Bar::bar必须与任何类一起工作,而不仅仅是Foo。我不知道传递给Bar::bar的实例指针是指向哪个类的。
唯一有用的信息是,所有将与Bar::bar一起使用的类都是一个类的子类!
这是否可行?如何修复我的代码?提前致谢!

使用std::function作为参数,当传递实际参数时,使用std::bind将成员函数与对象指针/引用/值绑定。 - Igor R.
1
这个问题有10亿个重复。 - Puppy
2个回答

9
您可以将bar变为一个模板函数:
template<class T>
void bar ( T* fooPtr , void(T::*fooFnPtr)() )
{
    (fooPtr->*fooFnPtr)();
}

当然,如果您只想传递指向存在于公共基类中的成员的指针,您可以简单地执行以下操作:
#include <iostream>

using namespace std;

class Foo
{
        public:
                virtual void foo ( )
                {
                        cout << "I'm a foo method\n";
                };
};

class Derived: public Foo
{
        public:
                virtual void foo ( )
                {
                        cout << "I'm a Derived method\n";
                };
};


class Bar
{
        public:
                void bar ( Foo* fooPtr , void(Foo::*fooFnPtr)() )
                {
                        (fooPtr->*fooFnPtr)();
                }
};

int main()
{
        Derived* derived = new Derived();
        Bar* bar = new Bar();

        bar->bar ( derived , &Foo::foo );

        return 0;
}

这个问题的唯一真正答案是 std::function。模板是一个不错的选择,但只适用于可模板化的函数,并不能使用 lambda 表达式或其他函数对象。 - Puppy
@DeadMG,你认为OP为什么需要lambda表达式或函数对象? - Henrik
因为它总是这样前进。更相关的是,std::function 现在成为标准的原因是因为 它是解决问题的正确方案 - Puppy
@DeadMG:问题标题非常明确:“指向未知类的成员函数指针”。此外,虽然问题中的简单示例可以使用std::function<void()>来绑定实例和成员,但在实际代码中,在对象之前或之后甚至在成员指针的多个用途中可能会有多个使用。最后,如果不需要更通用的方法,使用std::function将产生(最小的)开销。尽管这可能很小,但如果没有必要,为什么要付出呢? - David Rodríguez - dribeas
1
@DeadMG:我非常不喜欢这样的空洞陈述,因为指向成员和函数指针有正确的使用方法。请注意,问题不在于建议人们避免使用它们,而是声明它们总是要被避免。对我来说,这就像空洞地说“数组是指针”,这对大多数数组的用途(任何作为右值的用途)都是正确的,但会误导人们。顺便说一句,你可能没有意识到你正在称标准库为“糟糕的”API。 - David Rodríguez - dribeas
显示剩余6条评论

1

我猜你想要了解闭包和委托,或者在C++中的等效实现。简单来说,它们是可以被调用的实例,并且包含指向你的类实例(或实例本身)和方法的指针。

看一下std::bind。它们通常返回模板类的加密实例,这些实例都可以转换为std::function<...>,以便在函数或方法的参数中使用统一类型的参数。

因此,你的代码应该像这样:

    void Bar::bar(std::function<void()> f)
    { 
       ....
    }

    Foo* foo = new Foo();
    Bar* bar = new Bar();
    auto f = std::bind( &Foo::foo, foo);
    bar->bar ( f );

当然,如果您已经决定不使用任何库,您仍然可以看一下这些库是如何解决问题的,以便您能够以最佳方式重新发明轮子。


std::functionstd::bind是解决这个问题的唯一真正方案。 - Puppy
一个lambda怎么样?个人认为它们比绑定更易于阅读。 - bstamour
Lambdas很棒,但是 - 不考虑它们生成一个未命名类型(就像bind一样) - 我发现如果你只是将函数指针和实例绑定在一起,它们会掩盖意图。 - dsign

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