简体   繁体   中英

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

I have two classes, Sim and IElement . The class IElement defines a function pointer, whereas the class Sim has a vector of IElement pointers. What is the correct way to call the pointed-to function from the function pointer defined in IElement , given that I have a vector of IElement* ?

Or in another words, I have

std::vector<IElement*> nodes;

And I need to call a pointed-to function from IElement :

nodes[i]->*SetInput(); // ERROR: Identifier "SetInput" is undefined

I assume I'm having this error because nodes is a vector of pointers, and I am unaware of how to dereference nodes[i] before calling its pointed-to function.

Thank you for any advice.

A bit more detailed snippets of the code are given below.

The method of the Sim class where I am having the error Undefined identifier for the method of IElement

#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++;
    }
}

whereas in the Elements namespace, I have the class IElement declaration

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

and the class IElement implementation

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

You need to both get the SetInput member value from the IElement object, using a normal member operator, and then call the member function on the IElement object, using ->* . Assuming you want to use the same IElement for both:

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

Or perhaps rewrite the couple of statements as:

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

By the way, &(this->SetInput_Sum) is not an officially valid way to get a pointer to member. If your compiler accepts it, it's allowing it as an extension. The IElement constructor should be written:

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

This also seems like an XY Problem . C++ has classes that mean you can avoid the if in the first place by subclassing and having a normalized and non-normalized version of same. Override SetInput accordingly.

That plays out roughly like this:

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

    virtual void SetInput();
};

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

    virtual void SetInput();
};

Object-Oriented design principles generally steer towards using classes to do a lot of the work for you, avoiding the need for individual classes to differentiate like this.

You could always capture the boolean used on the constructor and just reference that as a property when performing whatever operations you need to, doing it procedurally within each function needing to know.

Simple example of calling method through pointer.

#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.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM