gpt4 book ai didi

c++ - 传递一个类成员函数作为函数参数

转载 作者:可可西里 更新时间:2023-11-01 18:17:56 26 4
gpt4 key购买 nike

我有 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 指针的语法真的很难看。

要定义一个名为 arg 的 NSMF 指针类型的变量(或参数),您可以这样做:

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 有一个名为 Function 的成员,它符合上面的 ReturnTypeParameterList,您将按如下方式填写 arg :

arg = &ClassName::Function;

规则 #3:非静态成员指针不是指针。是的,它们可以设置为 NULL(从技术上讲,它们可以设置为 0),但它们不是指针。

大多数真正的 C 和 C++ 编译器将允许您将函数指针转换为 void* 并返回。标准考虑了这种未定义的行为,但这样做并非完全未知。在几乎所有 C++ 编译器上,您绝对不能使用 NSMF 指针执行此操作。实际上,sizeof(MemberPointerType) 的大小可能与 void* 的大小不同。

因此,NSMF 指针不是常规指针。不要这样对待他们。

关于c++ - 传递一个类成员函数作为函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7218519/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com