将类成员函数作为函数参数传递

use*_*747 7 c++ syntax

我有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() );
    }

};
Run Code Online (Sandbox Code Playgroud)

第二个问题是:如上所述间接调用类成员(或静态)函数是不好(或危险)的做法.我有一种感觉这是非常糟糕的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");
    }
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 13

类的静态成员函数最终与常规函数没有区别.他们真的只是语法糖; 该函数只是包含一个名称Classname::.

非静态成员完全是另一回事.关于非静态成员函数(NSMF),有两件重要的事情需要记住.

首先,每个非静态成员函数都可以访问它们所属的类的非静态成员.即使您可以有两个同一类的对象碰巧存储不同的数据,这也是可能的.如果你有两个std::string对象,它们每个都存储不同的字符串.执行find一个字符串可以在一个字符串中返回找到的结果,而不是另一个字符串.

这是因为每个NSMF都有一个隐式this指针.this不仅指一个类,而且指NSMF运行的实际对象.当你这样做:

std::string aString("data");
aString.find("da");
Run Code Online (Sandbox Code Playgroud)

find函数采用字符串参数,但它也aString作为其参数this.每次find寻找同类的成员时,都会查看aString数据.

那么让我们来看看您对NSMF的预期召唤:

((*)nMemberFunction())
Run Code Online (Sandbox Code Playgroud)

从它获取this指针的对象在哪里?没有对象,NSMF无法访问对象的非静态成员,因为没有对象可以找到它们.这是不合法的.

因此,关于NSMF的规则#1:您必须使用NSMF所属的类的实际实例(或其派生类)调用它们.你不能只是拿一个NSMF指针并像函数指针一样调用它; 你必须在这种类型的活动对象上调用它.

规则#2:NSMF指针的语法非常难看.

要定义名为argNSMF指针类型的变量(或参数),请执行以下操作:

ReturnType (ClassName::*arg)(ParameterList);
Run Code Online (Sandbox Code Playgroud)

ReturnType函数的返回类型在哪里,是函数ParameterList采用的参数列表,ClassName是NSMF指针所属的类的名称.

鉴于丑陋,通常最好将其包装在typedef中:

typedef ReturnType (ClassName::*MemberPointerType)(ParameterList);
Run Code Online (Sandbox Code Playgroud)

从而创建了typedef MemberPointerType,它是一个NSMF指针.

给定一个名为的对象object,它是一个类型ClassName,你可以调用成员指针arg,如下所示:

ReturnType value = (object.*arg)(Params);
Run Code Online (Sandbox Code Playgroud)

Params你希望传递的论点在哪里?如果object是指向ClassName而不是引用或值的指针,则object->*arg改为使用.

还有一件事:您必须使用&获取成员指针名称.与函数指针不同,NSMF指针不会自动转换为成员指针.你必须直接问他们.所以,如果ClassName有一个成员叫功能适合以上ReturnTypeParameterList,你将填补arg如下:

arg = &ClassName::Function;
Run Code Online (Sandbox Code Playgroud)

规则#3:非静态成员指针不是指针.是的,他们可以设置为NULL(在技术上,它们可以被设置为0),但它们不是一回事指针.

大多数真正的C和C++编译器都允许您将函数指针强制转换为a void*和back.标准考虑了这种未定义的行为,但这并不是完全未知的.你绝对不能用NSMF指针做到这一点,几乎所有的C++编译器.实际上,这sizeof(MemberPointerType)可能与大小不同void*.

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