为什么成员函数指针不能被对应的成员正确访问?

4
考虑以下代码片段。
class B {
public:
    void up() {
        std::cout << "up" << std::endl;
    }
    void down() {
        std::cout << "down" << std::endl;
    }
    void init( void(B::*someFunc)() , void(B::*otherFunc)() ) {
        m_execute = someFunc;
        B* newB = new B();
        m_b = newB;
        m_b->m_execute = otherFunc;
    }

    void find() {
        (this->*m_execute)();
        (m_b->*m_execute)();
    }
private:
    void(B::*m_execute)();
    B* m_b;
};

int main(){
    B* b = new B();
    b->init(&B::up,&B::down);
    b->find();
}

我有一个类B。它的私有成员是指向B的指针m_b和函数指针。 在init()函数中,私有成员函数指针被赋值为up(),私有成员m_b的函数指针被赋值为down() 当我运行代码时,会执行两次B::up()而不是先执行B::up()再执行B::down()。


1
也许在find()的第二行,你想要的是(m_b->*(m_b->m_execute))()吗? - Daniel Schepler
1
笔误。你两次使用了相同的成员 m_execute。看起来你想写 (this->*m_execute)(); (m_b->*(m_b->m_execute))(); - Justin
1
啊,函数指针......它们难道不是......有趣吗 :) - NathanOliver
谢谢大家... @NathanOliver 哈哈...并不总是这样... - Rahul Naik
1个回答

5
这是因为您将一个对象的 m_execute 应用于另一个对象。
通过更改这行代码来修复它。
(m_b->*m_execute)();
//     ^^^^^^^^^
// Points to your m_execute, not m_b's

转换为:

(m_b->*m_b->m_execute)();

更好的方法是,添加一个成员函数来运行您自己的执行,并从B :: find 中调用它:
void find() {
    run_my_execute();
    m_b->run_my_execute();
}
void run_my_execute() {
    (this->*m_execute)();
}

这将避免混淆,即不知道应该将哪个指针应用于哪个对象。
演示链接:Demo.

哇...谢谢...因为这个问题我卡了很久...但是我还是不明白为什么它能够工作。m_b 是 B 的子类,所以我为什么不能像在 init() 中一样简单地使用 m_b->*m_execute 呢? - Rahul Naik
1
@RahulNaik,这不是关于m_b,而是关于m_execute。通过对象指针调用成员函数指针的语法是(ptr->*pmf)(...)。在这种情况下,成员函数指针属于m_b,所以你需要告诉编译器:(ptr->*(m_b->pmf))(...)。由于->的优先级高于->*,因此额外的括号是不必要的。对于你来说,ptrm_bpmfm_execute - chris
@chris 哦哦哦...不错..我之前不知道有这个优先级的事情。谢谢你。 - Rahul Naik
1
@RahulNaik的init函数访问了两个不同对象上的m_execute成员 - 它自己的m_execute = someFuncm_bm_b->m_execute = otherFunc。你的find()成员函数也可以访问这两个成员,因此它需要指定要调用哪一个。 - Sergey Kalinichenko

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