传递一个类的成员函数作为函数参数
我有2点C++类的问题:传递一个类的成员函数作为函数参数
的第一个问题是:我怎样才能使这样我就可以在另一个函数&传递类成员函数作为参数我怎么才能运行/调用该功能?我怎样才能做到类静态函数。它也许更容易被看这个代码明白我的问题:
class DebuggingManager
{
string testLog;
bool test1()
{
// run test & return whether it passed or failed
}
static bool test2()
{
}
// How can I call a member function?
void catalogueTest(string testName, bool DebuggingManager::*nMemberFunction)
{
testLog += "Status of " + testName + ": " + ((*)nMemberFunction()) + "\n";
}
// How can I call a static function?
void catalogueTest(string testName, bool DebuggingManager::*nStaticFunction)
{
testLog += "Status of " + testName + ": " + DebuggingManager::nStaticFunction() + "\n";
}
// how do I pass a member function or a static function as a parameter in another function
bool runTests()
{
catalogueTest("Test of member functin", test1());
catalogueTest("Test of static functin", test2());
}
};
的第二个问题是:是否有不良(或危险)的做法调用类成员(或静态)函数间接就像上面。我有一种感觉,这是非常糟糕的C++的做法?
编辑:实施意见 感谢您的答复,我试图实现他的意见,它的很多我的头左右,虽然,这会是正确的吗?
// I have a feeling that ParameterList is incorect, would I pass the implicit obj as a parameter or is it done automatically like in normal object function calls?
typedef bool (DebuggingManager::*MemberPointerType)(ParameterList);
void catalogueTest(tstring testName, DebuggingManager* obj, MemberPointerType *nMemberFunction)
{
debugLog += _T("Status of ") + testName + _T(": ") + (obj->*nMemberFunction)() + _T("\r\n");
}
void catalogueStaticTest(tstring testName, bool DebuggingManager::nStaticFunction)
{
debugLog += _T("Status of ") + testName + _T(": ") + nStaticFunction + _T("\r\n");
}
类的静态成员函数最终没有不同于普通函数。他们真的只是语法糖;该功能只是有一个名称,其中包括Classname::
。
非静态成员完全是另一回事。关于非静态成员函数(NSMF)有两件重要的事情要记住。首先,每个非静态成员函数都可以访问它们所属的类的非静态成员。即使可以有两个同一类的对象存储不同的数据,这也是可能的。如果您有两个std::string
对象,则它们每个都存储不同的字符串。对一个字符串执行find
可以在一个字符串中返回找到的结果,但不会在另一个字符串中返回。
这是因为每个NSMF都有一个隐含的指针this
。 this
指的不仅仅是一个类,而是NSMF在其上运行的实际的对象。当你这样做:
std::string aString("data");
aString.find("da");
的find
功能需要一个字符串参数,但它也得到aString
为this
。每次find
寻找其班级的成员,它会查看aString
的数据。
因此,让我们看看你的NSMF的前瞻性电话:
((*)nMemberFunction())
在哪里对象,它得到了this
指针的?没有对象,NSMF无法访问该对象的非静态成员,因为没有对象可供它找到它们。这是不合法的。
因此,有关NSMF的规则#1:您必须使用NSMF所属的类的实际实例(或其派生类)调用它们。你不能只带一个NSMF指针,并把它称为函数指针;您必须在该类型的实时对象上调用它。
规则2:NSMF指针的语法真的很难看。
定义一个名为NSMF指针类型的arg
变量(或参数),你这样做:
ReturnType (ClassName::*arg)(ParameterList);
哪里ReturnType
是函数的返回类型,ParameterList
是函数取的参数列表,并且ClassName
是NSMF指针所属的类的名称。
鉴于丑陋,通常最好将其包装在一个typedef:
typedef ReturnType (ClassName::*MemberPointerType)(ParameterList);
因此创建的typedef MemberPointerType
,这是一个NSMF指针。
给定一个名为object
的对象,这是ClassName
型的,你会调用成员指针arg
如下:
ReturnType value = (object.*arg)(Params);
哪里Params
是你要传递的参数。如果object
是指向ClassName
而不是参考或值的指针,则代之以使用object->*arg
。
还有一件事:你必须使用&
得到成员指针名称。与函数指针不同,NSMF指针不会自动转换为成员指针。你必须直接询问他们。所以,如果ClassName
有一个成员叫功能适合上述ReturnType
和ParameterList
,你将填补arg
如下:
arg = &ClassName::Function;
规则#3:非静态成员指针不是指针。是的,他们可以设置为NULL(技术上,它们可以设置为0),但它们是而不是与指针相同。
大多数真正的C和C++编译器将允许您将函数指针投射到void*
之后。标准认为这种未定义的行为,但这并不完全未知。你绝对是不能用在NSMF指针上做这件事,几乎所有的C++编译器都这样做。的确,sizeof(MemberPointerType)
的尺寸可能不会与void*
的尺寸相同。
因此,NSMF指针不是常规指针。不要这样对待他们。
难道你不得不说'(object。* arg)(Params);'因为运算符优先级? –
@Kerrek SB:是的,'。*'的优先级低于函数调用的优先级。 –
@Nicol Bolas:谢谢你的回复。我试图实现你所说的,这是对的吗? – user593747
在C++ 11中,他们想出了一个办法。阅读有关function和bind的操作。
就你而言,假设你想调用test1类型的函数。 (即形式布尔使用functionName()的
void catalogueTest(string testName, std::function<bool()> myFunction)
{
testLog += "Status of " + testName + ": " + myFunction() + "\n";
}
,并调用它是这样的:
DebuggingManager myInstance
myInstance->catalogueTest("TestName", std::bind(&DebuggingManager::test1, myInstance));
我很惊讶,这不是已经回答也许其他人是累过,不希望查找第500次成员函数指针的语法。 –
请参阅http:// stackoverflow。com/questions/2463112 /指向ac-class-member-function-as-a-global-functions-parameter的链接http://www.parashift.com/c++-faq-lite/pointers- to-members.html在声明/使用普通和静态成员函数指针时有注意的语法和注意事项。至于是否坏,我会说:可能不是在特定情况下(如测试或其他人),但作为编写代码的日常练习并不是一件好事,因为它很棘手,并且因为对于大多数您可以使用它们的任何东西都有更好的机制。 – shelleybutterfly