【问题标题】:Calling function from std::array of function pointers从函数指针的 std::array 调用函数
【发布时间】:2018-01-20 09:02:28
【问题描述】:

我不知道如何调用存储在类成员 std::array 中的函数指针。

namespace logic {
    class Chance {
        std::array<void(logic::Chance::*)(), 15> m_redChances;
    };
}

void logic::Chance::redChance1 {
   std::cout << "Red chance one\n";
}

logic::Chance::Chance()
{
    m_redChances[0] = &Chance::redChance1;
}

到目前为止看起来还不错,但是当我想在另一个成员函数中调用此函数时,似乎没有任何效果。只有第一行编译,但它不调用我的函数。其余的给出错误:

logic::Chance::anotherMemberFunction() {
    m_redChances[0];
    (*m_redChances[0]*)();
    (*logic::Chance::m_redChances[0])();
    m_redChances[0]();
    *m_redChances[0]();
    *logic::Chance::m_redChances[0]();
    *logic::Chance::m_redChances[0];
    *(*m_redChances[0])();
}

“*”的操作数必须是指针类型

apprent call 的括号前的表达式必须有 (pointer-to-) 函数类型

编辑#

所以我尝试使用std::function 并且不得不稍微改变类设计,我想实现这样的目标

struct Foo {
    std::array<std::function<void(Foo&)>, 3> funArray;

    Foo() {     
        funArray[0] = &Foo::fun1;
        funArray[1] = &Foo::fun2;       
    }

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

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

    std::function<void(Foo&)> getFunction(int i) {
        return funArray[i];
    }
};  

int main() {
    Foo foo;
    foo.getFunction(0);
    std::cin.get();
}

您可以猜到,这并没有调用我的函数,我再次尝试了每种组合以正确返回它,但无法弄清楚,这是唯一可以编译的,但什么也不做。如何返回另一个函数在std::array 中的函数调用?有点乱,但希望你明白我的意思。

【问题讨论】:

  • 类定义中没有声明的成员函数,以后不能定义。这可能是您错误的来源之一。此外,函数定义至少需要一个空的形式参数列表,()

标签: c++ arrays std function-pointers


【解决方案1】:

std::array&lt;void(logic::Chance::*)(), 15&gt; m_redChances 是一个指针数组,指向一个static 成员函数Chance 的对象。因此,您需要应用将要调用指向的成员函数的对象。

在声明中:

(*logic::Chance::m_redChances[0])();

没有提供任何对象。该调用将在哪个对象的数据上执行?

考虑到chanceChance 的对象,而chance_ptr 是指向同一类型对象的指针,调用将以这种方式执行:

(chance.*m_redChances[0])();
(chance_ptr->*m_redChances[0])();

即分别使用运算符.*-&gt;*

【讨论】:

    【解决方案2】:

    在您的 std::function 示例中,您可以简单地更改

    foo.getFunction(0);
    

    改为说

    foo.getFunction(0)(foo);
    

    这与其他答案中谈到的相同原因有关,指向成员函数的指针本身并不链接到对象。它需要this 才能工作。

    如果您想将 std::function 绑定到特定对象,您可以使用 lambda 来做到这一点,就像这样。

    #include <iostream>
    #include <array>
    #include <functional>
    
    struct Foo {
        std::array<std::function<void()>, 3> funArray; // Notice the change in signature to void()
    
        Foo() {     
            funArray[0] = [&](){ fun1(); }; // Here & is catching this by reference and this lambda will always call fun1 on the current object.
            funArray[1] = [&](){ fun2(); };
        }
    
        void fun1() {
            std::cout << "fun1\n";
        }
    
        void fun2() {
            std::cout << "fun2\n";
        }   
    
        std::function<void()> getFunction(int i) {
            return funArray[i];
        }
    };  
    
    int main() {
        Foo foo;
        foo.getFunction(0)(); // We get a function returned, so we need to call if by adding one more () at the end
    
    
        auto storedFunction = foo.getFunction(1); // We can also store it
        storedFunction(); // and call it later
    }
    

    【讨论】:

    • 我稍微修改了一段代码,以便我的函数可以返回一些内容。 std::array&lt;std::function&lt;std::string()&gt;, 3&gt; funArray; 和内部 Foo() 构造函数 funArray[0] = [&amp;]() -&gt; std::string { fun1(); }; 。但它无法编译,出现此错误:error C4716: '::operator()': must return a value
    • 改成返回 fun1();在 lambda 内部,因此 lambda 从函数返回值。
    【解决方案3】:

    需要在对象上调用成员函数,以充当*this当前对象。您可以使用.*-&gt;* 操作符来调用一个对象。例如。 (o.*mf)( args ).

    Andrei 在他的 Modern C++ Programming 一书中指出的愚蠢事实:o.*mf 产生一个没有类型的可调用实体。

    在 C++11 及更高版本中,您可以使用std::function 将这样的对象+函数指针对有效地存储为可调用实体。其他一些语言直接支持它。例如,它对应于 C# delegate


    示例。

    #include <array>
    #include <iostream>
    using namespace std;
    
    struct Foo
    {
        void blah() { cout << "Blah!" << endl; }
    };
    
    auto main()
        -> int
    {
        array<void (Foo::*)(), 3> mf = {nullptr, nullptr, &Foo::blah};
    
        Foo o;
        Foo* o_ptr = &o;
    
        (o_ptr->*mf[2])();
    }
    

    【讨论】:

    • 如果我需要在this对象上使用怎么办?例如,我尝试了(this-&gt;*m_redChances[0])();,但它没有用
    • “没用”太含糊了。但那是-&gt;* 运算符,你有这个权利。例如。 (this-&gt;*mf)()。或者,您可以取消引用 this 并使用 .*,例如 ((*this).*mf)()
    • 我在答案中添加了一个完整的例子。
    猜你喜欢
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2018-04-14
    • 1970-01-01
    相关资源
    最近更新 更多