指针对成员函数的实际用途是什么? [英] What is the practical use of pointers to member functions?

查看:116
本文介绍了指针对成员函数的实际用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了这篇文章,以及我从中学到的东西当你想调用一个指向成员函数的指针时,你需要一个实例(指向一个指针或一个堆栈引用),并调用它:

I've read through this article, and what I take from it is that when you want to call a pointer to a member function, you need an instance (either a pointer to one or a stack-reference) and call it so:

(instance.*mem_func_ptr)(..)
or
(instance->*mem_func_ptr)(..)

我的问题是基于这个:因为你有实例,为什么不直接调用成员函数,

My question is based on this: since you have the instance, why not call the member function directly, like so:

instance.mem_func(..) //or: instance->mem_func(..)

成员函数指针的合理/实际使用是什么?

What is the rational/practical use of pointers to member functions?

我在玩X-development&到达我正在实现小部件的阶段;用于将X事件转换为我的类&当它们的事件到达时,窗口小部件需要为每个窗口/窗口启动线程;为了做到这一点,我认为我需要函数指针到我的类中的事件处理程序。

I'm playing with X-development & reached the stage where I am implementing widgets; the event-loop-thread for translating the X-events to my classes & widgets needs to start threads for each widget/window when an event for them arrives; to do this properly I thought I needed function-pointers to the event-handlers in my classes.

不是这样:我发现我可以做同样的事情在一个更清楚和更简单的方式通过简单地使用虚拟基类。不需要任何指向成员函数的指针。在开发上述内容时,对成员函数指针的实际可用性/含义的怀疑就出现了。

Not so: what I did discover was that I could do the same thing in a much clearer & neater way by simply using a virtual base class. No need whatsoever for pointers to member-functions. It was while developing the above that the doubt about the practical usability/meaning of pointers to member-functions arose.

为了使用成员函数指针,你需要一个实例引用的简单的事实,取消了对一个实例的需要。

The simple fact that you need a reference to an instance in order to use the member-function-pointer, obsoletes the need for one.

[edit - @sbi&其他]

[edit - @sbi & others]

这是一个示例程序来说明我的观点:$ b​​ $ b(特别注意Handle_THREE())

Here is a sample program to illustrate my point: (Note specifically 'Handle_THREE()')

#include <iostream>
#include <string>
#include <map>


//-----------------------------------------------------------------------------
class Base
{
public:
    ~Base() {}
    virtual void Handler(std::string sItem) = 0;
};

//-----------------------------------------------------------------------------
typedef void (Base::*memfunc)(std::string);

//-----------------------------------------------------------------------------
class Paper : public Base
{
public:
    Paper() {}
    ~Paper() {}
    virtual void Handler(std::string sItem) { std::cout << "Handling paper\n"; }
};

//-----------------------------------------------------------------------------
class Wood : public Base
{
public:
    Wood() {}
    ~Wood() {}
    virtual void Handler(std::string sItem) { std::cout << "Handling wood\n"; }
};


//-----------------------------------------------------------------------------
class Glass : public Base
{
public:
    Glass() {}
    ~Glass() {}
    virtual void Handler(std::string sItem) { std::cout << "Handling glass\n"; }
};

//-----------------------------------------------------------------------------
std::map< std::string, memfunc > handlers;
void AddHandler(std::string sItem, memfunc f) { handlers[sItem] = f; }

//-----------------------------------------------------------------------------
std::map< Base*, memfunc > available_ONE;
void AddAvailable_ONE(Base *p, memfunc f) { available_ONE[p] = f; }

//-----------------------------------------------------------------------------
std::map< std::string, Base* > available_TWO;
void AddAvailable_TWO(std::string sItem, Base *p) { available_TWO[sItem] = p; }

//-----------------------------------------------------------------------------
void Handle_ONE(std::string sItem)
{
    memfunc f = handlers[sItem];
    if (f)
    {
        std::map< Base*, memfunc >::iterator it;
        Base *inst = NULL;
        for (it=available_ONE.begin(); ((it != available_ONE.end()) && (inst==NULL)); it++)
        {
            if (it->second == f) inst = it->first;
        }
        if (inst) (inst->*f)(sItem);
        else std::cout << "No instance of handler for: " << sItem << "\n";
    }
    else std::cout << "No handler for: " << sItem << "\n";
}

//-----------------------------------------------------------------------------
void Handle_TWO(std::string sItem)
{
    memfunc f = handlers[sItem];
    if (f)
    {
        Base *inst = available_TWO[sItem];
        if (inst) (inst->*f)(sItem);
        else std::cout << "No instance of handler for: " << sItem << "\n";
    }
    else std::cout << "No handler for: " << sItem << "\n";
}

//-----------------------------------------------------------------------------
void Handle_THREE(std::string sItem)
{
    Base *inst = available_TWO[sItem];
    if (inst) inst->Handler(sItem);
    else std::cout << "No handler for: " << sItem << "\n";
}


//-----------------------------------------------------------------------------
int main()
{
    Paper p;
    Wood w;
    Glass g;


    AddHandler("Paper", (memfunc)(&Paper::Handler));
    AddHandler("Wood", (memfunc)(&Wood::Handler));
    AddHandler("Glass", (memfunc)(&Glass::Handler));

    AddAvailable_ONE(&p, (memfunc)(&Paper::Handler));
    AddAvailable_ONE(&g, (memfunc)(&Glass::Handler));

    AddAvailable_TWO("Paper", &p);
    AddAvailable_TWO("Glass", &g);

    std::cout << "\nONE: (bug due to member-function address being relative to instance address)\n";
    Handle_ONE("Paper");
    Handle_ONE("Wood");
    Handle_ONE("Glass");
    Handle_ONE("Iron");

    std::cout << "\nTWO:\n";
    Handle_TWO("Paper");
    Handle_TWO("Wood");
    Handle_TWO("Glass");
    Handle_TWO("Iron");

    std::cout << "\nTHREE:\n";
    Handle_THREE("Paper");
    Handle_THREE("Wood");
    Handle_THREE("Glass");
    Handle_THREE("Iron");
}






< >上述示例中的直接调用的潜在问题:

在Handler_THREE()中,方法的名称必须是硬编码的,强制在使用它的任何地方进行更改,对方法应用任何更改。


{edit] Potential problem with direct-call in above example:
In Handler_THREE() the name of the method must be hard-coded, forcing changes to be made anywhere that it is used, to apply any change to the method. Using a pointer to member-function the only additional change to be made is where the pointer is created.

从答案中收集的实际用途

[edit] Practical uses gleaned from the answers:

From answer by Chubsdad:
What: A dedicated 'Caller'-function is used to invoke the mem-func-ptr;
Benefit: To protect code using function(s) provided by other objects
How: If the particular function(s) are used in many places and the name and/or parameters change, then you only need to change the name where it is allocated as pointer, and adapt the call in the 'Caller'-function. (If the function is used as instance.function() then it must be changed everywhere.)

Matthew Flaschen的回答

什么:一个类
优点:使代码更清晰,更简单,更易于使用和维护
如何:用可能的大型switch()/ if-then语句替换通常使用复杂逻辑实现的代码直接指向专业化;非常类似于上面的Caller函数。

From answer by Matthew Flaschen:
What: Local specialization in a class
Benefit: Makes the code much clearer,simpler and easier to use and maintain
How: Replaces code that would conventionally be implement using complex logic with (potentially) large switch()/if-then statements with direct pointers to the specialization; fairly similar to the 'Caller'-function above.

推荐答案

有很多实际用途。我想到的是如下:

There are many practical uses. One that comes to my mind is as follows:

假设一个核心函数如下(适当定义myfoo和MFN)

Assume a core function such as below (suitably defined myfoo and MFN)

void dosomething(myfoo &m, MFN f){   // m could also be passed by reference to 
                                     // const
   m.*f();
}

在存在成员函数指针的情况下,并关闭以进行修改( OCP

Such a function in the presence of pointer to member functions, becomes open for extension and closed for modification (OCP)

另请参阅安全bool惯用语,它巧妙地使用指向成员的指针。

Also refer to Safe bool idiom which smartly uses pointer to members.

这篇关于指针对成员函数的实际用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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