我有两个班,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);
}
}
答案 0 :(得分:2)
您都需要使用常规成员运算符从SetInput
对象中获取IElement
成员值,然后使用{{1 }}。假设您要对两者使用相同的IElement
:
->*
或者将这两个语句重写为:
IElement
顺便说一句,(nodes[i]->*(nodes[i]->SetInput))();
并不是获得指向成员的指针的官方有效方法。如果您的编译器接受它,则允许它作为扩展。 Elements::IElement* node = Elements::GetElement(i);
nodes[i] = node;
(node->*(node->SetInput))();
构造函数应编写为:
&(this->SetInput_Sum)
答案 1 :(得分:1)
这似乎也像XY Problem。 C ++具有一些类,这些类意味着您可以首先通过子类化并拥有相同版本的标准化和非标准化版本来避免if
。相应地覆盖SetInput
。
播放效果大致如下:
class IElement
{
public:
IElement();
virtual ~IElement();
virtual void SetInput();
};
class IElementNormalized : IElement {
IElementNormalized();
virtual ~IElementNormalized();
virtual void SetInput();
};
面向对象的设计原则通常会引导您使用类为您完成很多工作,而无需像这样的单个类进行区分。
您始终可以捕获构造函数上使用的布尔值,并在执行所需的任何操作时将其作为属性引用,在需要了解的每个函数中按程序进行操作。
答案 2 :(得分:1)
通过指针调用方法的简单示例。
#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.
}