将类成员函数作为函数参数传递 [英] Pass a class member function as a function parameter

查看:111
本文介绍了将类成员函数作为函数参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个C ++类问题:

第一个问题是:如何做到这一点,以便可以传递类成员函数作为另一个函数&中的参数然后如何运行/调用该函数?以及如何使用类静态函数执行相同操作。通过查看以下代码,可能更容易理解我的问题:

The 1st question is: How can I make it so I can pass a class member function as a parameter in another function & how can I then run/call that function? And how can I do the same with a class static function. It maybe easier to understand my question by looking at this code:

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 ++的一种不好的做法?

The 2nd question is: Is it bad(or dangerous) practice to call a class member (or static) function indirectly like the above. I have a feeling this is really bad C++ practice?

编辑:实施建议
感谢您的答复,我试图实施该建议,尽管它可以引起我的注意,这是否正确?

Implementing advice Thanks for the reply, I have attempted to implement that advice, its alot to get my head around though, would this be correct?

    // 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 :: 的名称。

Static member functions of classes are ultimately no different than regular functions. They're really just syntactic sugar; the function is simply has a name that include Classname::.

非静态成员是另一回事。关于非静态成员函数(NSMF),有两点要记住。

Non-static members are another matter altogether. There are two important things to remember about non-static member functions (NSMF).

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

First, every non-static member function has access to the non-static members of the class that they are a member of. This is possible even though you can have two objects of the same class that happen to store different data. If you have two std::string objects, they each store different strings. Executing a find on one string can return a found result in one but not the other.

这是因为每个NSMF有一个隐式 this 指针。 不仅指类,还指NSMF操作所基于的实际对象。当您这样做时:

This is because every NSMF has an implicit this pointer. this refers to, not merely a class, but the actual object upon which that NSMF operates. When you do this:

std::string aString("data");
aString.find("da");

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

The find function takes a string argument, but it also gets aString as its this. Every time find looks for the members of its class, it will be looking at aString's data.

因此,让我们看一下您对NSMF的预期调用:

So let's look at your prospective call of an NSMF:

((*)nMemberFunction())

在哪里得到它的对象 this 指针从哪里来?如果没有对象,则NSMF无法访问该对象的非静态成员,因为没有对象可以在其中找到它们。这是不合法的。

Where is the object that it gets its this pointer from? Without an object, the NSMF could not access the non-static members of the object, since there is no object for it to find them in. This is not legal.

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

So, rule #1 about NSMFs: You must call them with an actual instance of the class that the NSMF is a member of (or a derived class thereof). You cannot just take an NSMF pointer and call it like a function pointer; you have to call it on a live object of that type.

规则2:NSMF指针的语法确实很丑。

Rule #2: the syntax for NSMF pointers is really ugly.

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

To define a variable (or argument) named arg of NSMF pointer type, you do this:

ReturnType (ClassName::*arg)(ParameterList);

其中 ReturnType 是返回值的类型函数, ParameterList 是该函数采用的参数列表, ClassName 是该类要使用的类的名称

Where ReturnType is the return type of the function, ParameterList is the list of arguments taken by the function, and ClassName is the name of the class to which the NSMF pointer belongs.

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

Given the ugliness, it is usually best to wrap it in a typedef:

typedef ReturnType (ClassName::*MemberPointerType)(ParameterList);

因此创建typedef MemberPointerType

Thus creating the typedef MemberPointerType, which is a NSMF pointer.

给出一个名为 object 的对象,该对象的类型为 ClassName ,您将按以下方式调用成员指针 arg

Given an object named object, which is of type ClassName, you would call the member pointer arg as follows:

ReturnType value = (object.*arg)(Params);

其中 Params 是您想要的参数通过。如果 object 是指向 ClassName 的指针,而不是引用或值,则使用 object-> * arg

Where Params are the arguments you wish to pass. If object is a pointer to a ClassName instead of a reference or a value, then you use object->*arg instead.

另一件事:您必须使用& 来获取成员指针名称。与函数指针不同,NSMF指针不会自动转换为成员指针。您必须直接要求他们。因此,如果 ClassName 具有一个名为Function的成员,且该成员符合上面的 ReturnType ParameterList ,则按以下方式填充 arg

One more thing: you must use & to get the member pointer name. Unlike function pointers, NSMF pointers do not automatically convert to member pointers. You have to ask for them directly. So if ClassName has a member called Function that fit the above ReturnType and ParameterList, you would fill arg as follows:

arg = &ClassName::Function;

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

Rule #3: non-static member pointers are not pointers. Yes, they can be set to NULL (technically, they can be set to 0), but they are not the same thing as a pointer.

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

Most real C and C++ compilers will allow you to cast a function pointer to a void* and back. The standards consider this undefined behavior, but it's not-entirely-unknown to do this. You absolutely cannot do this with a NSMF pointer, on virtually all C++ compilers. Indeed, the sizeof(MemberPointerType) will likely not be the same size as void*.

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

So, NSMF pointers are not regular pointers. Do not treat them as such.

这篇关于将类成员函数作为函数参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆