如何从 C++ 中实例化对象的函数指针调用函数?

How to call a function from a function pointer of an instantiated object in C++?

我有两个 class,SimIElement。 class IElement 定义了一个函数指针,而 class Sim 有一个 IElement 指针向量。鉴于我有一个 IElement* 的向量,从 IElement 中定义的函数指针调用指向函数的正确方法是什么?

换句话说,我有

std::vector<IElement*> nodes;

我需要从 IElement:

调用一个指向函数
nodes[i]->*SetInput(); // ERROR: Identifier "SetInput" is undefined

我假设我有这个错误,因为 nodes 是一个指针向量,我不知道如何在调用它的指向函数之前取消引用 nodes[i]

感谢您的任何建议。

下面给出了更详细的代码片段。

Sim class 的方法 IElement

的方法出现错误 Undefined identifier
#include <vector>
#include "Elements.h" // defines class IElement in namespace Elements
void Sim::CreateNodes(int N) // this method belongs to the Sim class in namespace "Simulations"
{
    nodes = std::vector<Elements::IElement*>(N);
    int i = 0;
    while (i < N)
    {
        nodes[i] = new Elements::IElement(true); // for the sake of the example
        nodes[i]->*SetInput(); // ERROR: Identifier "SetInput" is undefined
        i++;
    }
}

而在 Elements 命名空间中,我有 class IElement 声明

class IElement
{
public:
    typedef void(IElement::*SetInputFc_ptr)();
    IElement(bool); // normalizeInput
    ~IElement();
    SetInputFc_ptr SetInput;
};

和 class IElement 实现

IElement::IElement(bool normalizeInput)
{
    if (normalizeInput)
    {
        this->SetInput= &(this->SetInput_Sum);
    }
    else
    {
        this->SetInput= &(this->SetInput_Const);
    }
}

您需要使用普通成员运算符从 IElement 对象获取 SetInput 成员值,然后使用 IElement 对象调用成员函数 ->*。假设您想对两者使用相同的 IElement

(nodes[i]->*(nodes[i]->SetInput))();

或者将这对语句重写为:

Elements::IElement* node = Elements::GetElement(i);
nodes[i] = node;
(node->*(node->SetInput))();

顺便说一下,&(this->SetInput_Sum) 不是获取指向成员的指针的官方有效方法。如果你的编译器接受它,它允许它作为一个扩展。 IElement 构造函数应该写成:

IElement::IElement(bool normalizeInput)
{
    if (normalizeInput)
    {
        this->SetInput= &IElement::SetInput_Sum;
    }
    else
    {
        this->SetInput= &IElement::SetInput_Const;
    }
}

这看起来也像 XY Problem。 C++ 具有 类,这意味着您可以首先通过子类化并具有相同的规范化和 non-normalized 版本来避免 if。相应地覆盖 SetInput

结果大致是这样的:

class IElement
{
public:
    IElement();
    virtual ~IElement();

    virtual void SetInput();
};

class IElementNormalized : IElement {
    IElementNormalized();
    virtual ~IElementNormalized();

    virtual void SetInput();
};

Object-Oriented 设计原则通常倾向于使用 类 为您完成大量工作,避免需要个人 类 像这样进行区分。

您始终可以捕获构造函数上使用的布尔值,并在执行您需要的任何操作时将其作为 属性 引用,在每个需要知道的函数中按程序执行。

通过指针调用方法的简单例子

#include <vector>

class IElement
{
    public:
        void action() {}
};

using MemberPtr = void (IElement::*)();    
MemberPtr Action = &IElement::action;

int main()
{
    std::vector<IElement*>  nodes{1, new IElement};

    (nodes[0]->*Action)();
    // Note the braces around the expression before the call.
    // This is because `()` binds tighter than `->*` so you need the
    // extra braces to force the `->*` to bind first so you can then call
    // the resulting method.

    //  nodes[0]->*Action();  // This will not compile.
}