简体   繁体   English

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

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

I have two classes, Sim and IElement . 我有两个类SimIElement The class IElement defines a function pointer, whereas the class Sim has a vector of IElement pointers. IElement类定义函数指针,而Sim类则具有IElement指针向量。 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* ? 什么是调用指向的自定义函数指针函数的正确方法IElement ,因为我有一个向量IElement*

Or in another words, I have 换句话说,我有

std::vector<IElement*> nodes;

And I need to call a pointed-to function from IElement : 我需要从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. 我以为我有这个错误,因为nodes是指针的向量,并且在调用其指向函数之前我不知道如何解引用nodes[i]

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 我有错误的IElement方法的Undefined identifierSim类的方法

#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 而在Elements命名空间中,我有IElement类声明

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

and the class IElement implementation 和类IElement实现

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 ->* . 您都需要使用常规成员运算符从IElement对象获取SetInput成员值,然后使用->*IElement对象上调用成员函数。 Assuming you want to use the same IElement for both: 假设您要对两个都使用相同的IElement

(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. 顺便说一句, &(this->SetInput_Sum)不是获得指向成员的指针的官方有效方法。 If your compiler accepts it, it's allowing it as an extension. 如果您的编译器接受它,则允许它作为扩展。 The IElement constructor should be written: IElement构造函数应编写为:

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

This also seems like an XY Problem . 这似乎也像XY问题 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. C ++具有一些类,这些类意味着您可以首先通过子类化并拥有相同版本的标准化和非标准化版本来避免if出现。 Override SetInput accordingly. 相应地重写SetInput

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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