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.