Как вызвать функцию из указателя функции экземпляра объекта в C ++? - PullRequest
0 голосов
/ 04 июня 2019

У меня есть два класса, Sim и IElement.Класс IElement определяет указатель на функцию, тогда как класс Sim имеет вектор IElement указателей.Как правильно вызывать указанную функцию из указателя функции, определенного в IElement, если у меня есть вектор IElement*?

Или, другими словами, у меня есть

std::vector<IElement*> nodes;

И мне нужно вызвать указанную функцию из IElement:

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

Я предполагаю, что у меня возникает эта ошибка, потому что nodes - это вектор указателей, и яне зная, как разыменовать nodes[i] перед вызовом функции, на которую он указывает.

Спасибо за любой совет.

Ниже приведены более подробные фрагменты кода.

Метод класса Sim, где у меня ошибка Undefined identifier для метода 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++;
    }
}

, тогда как в пространстве имен Elements у меня есть класс IElementдекларация

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

и класс IElement реализация

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

Ответы [ 3 ]

2 голосов
/ 04 июня 2019

Необходимо получить значение члена SetInput из объекта IElement, используя обычный оператор-член, а затем вызвать функцию-член для объекта 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;
    }
}
1 голос
/ 04 июня 2019

Простой пример вызова метода через указатель.

#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.
}
1 голос
/ 04 июня 2019

Это также похоже на проблему XY .В C ++ есть классы, которые означают, что вы можете избежать if в первую очередь, создав подклассы и имея нормализованную и ненормализованную версию того же самого.Переопределите SetInput соответственно.

Это выглядит примерно так:

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

    virtual void SetInput();
};

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

    virtual void SetInput();
};

Принципы объектно-ориентированного проектирования обычно направлены на использование классов для выполнения за вас большой работы, избегаянеобходимо, чтобы отдельные классы различались следующим образом.

Вы всегда можете захватить логическое значение, используемое в конструкторе, и просто ссылаться на него как на свойство при выполнении любых необходимых вам операций, делая это процедурно внутри каждой функции, которую нужно знать.

...