简体   繁体   English

C ++:在另一个对象中存储指向某个对象的成员函数的指针

[英]C++: Store pointer to a member function of an object in another object

I have a class which shall invoke a function specified by the user on certain occasions. 我有一个类,它将在某些情况下调用用户指定的功能。 Therefore the class has a method void setExternalPostPaintFunction(void(*function)(QPainter&)); 因此,该类具有方法void setExternalPostPaintFunction(void(*function)(QPainter&)); that can be used to "register" a function. 可以用来“注册”功能。 This function then will be called on that occasion: 然后将在这种情况下调用此函数:

class A {
    public:
        void setExternalPostPaintFunction(void(*function)(QPainter&));
    private:
        void (*_externalPostPaint)(QPainter&);
        bool _externalPostPaintFunctionAssigned;
};

The function pointer is saved in the member variable _externalPostPaint . 函数指针保存在成员变量_externalPostPaint The implementation of setExternalPostPaintFunction looks like this: setExternalPostPaintFunction的实现如下所示:

void A::setExternalPostPaintFunction(void(*function)(QPainter&)) {
    _externalPostPaint = function;
    _externalPostPaintFunctionAssigned = true;
}

Now, this works with normal functions. 现在,这可以正常使用。 However, I want to be able to also pass pointers to member functions of objects. 但是,我希望也能够将指针传递给对象的成员函数 From what I know I also have to pass and store the pointer to the object in this case. 据我所知,在这种情况下,我还必须传递并存储指向该对象的指针。 However, I don't know which type the other object will have. 但是,我不知道其他对象将具有哪种类型。 So I guess I'm forced to use templates. 所以我想我被迫使用模板。 I already thought of something like this: 我已经想到过这样的事情:

class A {
    public:
        template <typename T>
        void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
    private:
        void (T::*_externalPostPaint)(QPainter&);       //<- This can't work!
        bool _externalPostPaintFunctionAssigned;
};

This way I can pass a function pointer and an object pointer to setExternalPostPaintFunction and would probably be able to call the function on the object inside that function. 这样,我可以将一个函数指针和一个对象指针传递给setExternalPostPaintFunction ,并且可能能够在该函数内部的对象上调用该函数。 But I'm not able to store it in the variable _externalPostPaint because the type T is only deduced when the function setExternalPostPaintFunction is called, thus I can't have a member variable that depends on this type, since the type of my member variable has to be known when the object is created and apart from that it cannot change, but it would have to in the case when a new function is assigned which possibly could be a member function of an object of different type. 但是我无法将其存储在变量_externalPostPaint因为类型T仅在调用函数setExternalPostPaintFunction时才推导,因此我无法拥有依赖于此类型的成员变量,因为我的成员变量的类型具有要知道创建对象的时间,除此之外不能更改,但是必须在分配了新功能的情况下(可能是不同类型对象的成员功能)。

So what is the proper way to do this, or is there any? 那么执行此操作的正确方法是什么? I'm not super fit with templates and function pointers, so I might have overlooked something. 我不太适合使用模板和函数指针,因此我可能忽略了一些东西。

Anoter option would certainly be to create a functor class with a virtual member function which can be overwritten in a derived class and then pass + store an object pointer of that type instead of the function pointer. 另一个选择当然是使用虚拟成员函数创建函子类,该成员函数可以在派生类中被覆盖,然后通过+存储该类型的对象指针而不是函数指针。 But I somehow would prefer my approach if it is somehow possible. 但是,如果有可能,我会以某种方式更喜欢我的方法。

EDIT: SOLUTION 编辑:解决方案

TartanLlama brought me on the right track by suggesting the use of std::function . TartanLlama通过建议使用std::function使我走上了正确的轨道。 Here is how I solved it: 这是我解决的方法:

class A {
    public:
        template <typename T>
        void setExternalPostPaintFunction(T* object, void(T::*function)(QPainter&)) {
            _externalPostPaint = std::bind(function, object, std::placeholders::_1);
            _externalPostPaintFunctionAssigned = true;
        }
        void setExternalPostPaintFunction(std::function<void(QPainter&)> const& function);
    private:
        std::function<void(QPainter&)> _externalPostPaint;
        bool _externalPostPaintFunctionAssigned;
};

As you see, the pointer to the function/member function is stored in an std::function<void(QPainter&)> object now. 如您所见,函数/成员函数的指针现在存储在std::function<void(QPainter&)>对象中。 The advantage is, that an std::function can basically store any callable target. 优点是std::function基本上可以存储任何可调用目标。 Then there are two overloads: one that can be used for any std::function object that also accepts eg a normal function pointer (because the std::function that is expected then is implicitly constructed from that) and one for member functions that have to be called on an object (more for convenience). 然后有两个重载:一个重载可用于任何std::function对象,该对象也接受例如普通的函数指针(因为预期的std::function会由此隐式构造),另一个重载用于具有在对象上被调用(为方便起见)。 The latter is implemented as a template. 后者被实现为模板。 This uses std::bind to create a std::function object of the call of that member function (the user passed) on the object (the user passed). 这使用std::bind在对象(用户通过)上创建该成员函数(用户通过)的调用的std::function对象。

The overload that takes an std::function is implemented in the source file like this: 需要在源文件中实现std::function的重载是这样的:

void ImageView::setExternalPostPaintFunction(std::function<void(QPainter&)> const& function) {
    _externalPostPaint = function;
    _externalPostPaintFunctionAssigned = true;
}

Invoking that stored function in the code of class A is now as simple as that: 现在,在类A的代码中调用该存储的函数非常简单:

//canvas is a QPainter instance    
if (_externalPostPaintFunctionAssigned) _externalPostPaint(canvas);

The user who wants to register a member function as callback function just has to do the following: 想要将成员函数注册为回调函数的用户只需执行以下操作:

//_imageView is an instance of "A"
//"MainInterface" is the type of "this"
_imageView->setExternalPostPaintFunction(this, &MainInterface::infoPaintFunction);

Or if it's not a member function but just a normal function: 或者,如果它不是成员函数,而是普通函数:

void someFunction(QPainter& painter) {
    //do stuff
}

_imageView->setExternalPostPaintFunction(&someFunction);

Or he can explicitly create a std::function object and pass it: 或者,他可以显式创建一个std::function对象并传递它:

std::function<void(QPainter&)> function = [&](QPainter& painter){ this->infoPaintFunction(painter); };
_imageView->setExternalPostPaintFunction(function);

Works like a charm. 奇迹般有效。

You could use std::function : 您可以使用std::function

class A {
    public:
        //PostPaintFun can be anything which acts as a function taking a QPainter&
        //Could be a lambda, function pointer, functor, etc.
        using PostPaintFun = std::function<void(QPainter&)>;
        void setExternalPostPaintFunction(PostPaintFun fun);
    private:
        //Names beginning with an underscore are reserved, don't use them
        //Ending with an underscore is fine
        PostPaintFun fun_;
        bool externalPostPaintFunctionAssigned_;
};

Now you can use member functions like so: 现在,您可以像这样使用成员函数:

struct B
{
    void exec(QPainter&) const;
};

void foo() {
    B b;
    a.setExternalPostPaintFunction(
        [b] (QPainter& p) {b.exec(p);}
    );
}

//or inside B
void B::foo() {
    a.setExternalPostPaintFunction(
        [this] (QPainter&p) {this->exec(p);}
    );
 }

I have to say I prefer TartanLlama's answer, but here you have something it could work for you. 我不得不说我更喜欢TartanLlama的答案,但是在这里您可以使用一些适合您的东西。

This might to need some work, but I'm sure you'll get the idea. 这可能需要一些工作,但是我相信您会明白的。

struct IFunctionHolder {};                      // Used for pointing to any FunctionHolder
typedef IFunctionHolder* functionHolder_ptr;    // Alias for IFunctionHolder* .

template<typename Function>                     // The template for the actual function holders.
struct FunctionHolder:  public IFunctionHolder
{
    Function function;
};


class A {
    public:
        template <typename T>
        void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
    private:
        functionHolder_ptr *function_holder;            // This memeber can hold eny instantiation of template<> FunctionHolder.
                                                        // Instantiate this member wen calling setExternalPostPaintFunction
        bool _externalPostPaintFunctionAssigned;
};

You could have some code like this: 您可能会有类似以下的代码:

A some_a;
void some_a.setExternalPostPaintFunction(&SomeInstance::some_fnunction);    // Here take place the instantiation of FunctionHolder.
some_a.function_holder.function(some_painter);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++函数指针,指向静态指针对象的成员函数 - C++ Function pointer to member function of a static pointer object 在c ++中将成员函数指针传递给成员对象 - Passing member function pointer to member object in c++ 将成员函数传递给另一个对象的成员函数C ++ - Passing member function to another object's member function C++ C ++。 如何将对象指针传递给函数内的成员函数 - C++ . How to pass an object pointer into a member function within a function c ++ - 在取消引用的对象指针上调用成员函数 - c++ - call member function on dereferenced object pointer C ++指针可以在没有对象的情况下调用成员函数 - C++ Pointer can call Member Function without Object 通过指针 C++ 调用成员 function,object 是 Z37A6259CC0C1DAE0BD9A7866489DFF - Calling member function via pointer C++, object is null? 使用从C ++对象到另一个C ++对象的指针,从Lua修改成员变量 - using a pointer from a C++ object, to another C++ object, to modify member variables, from Lua C ++转换:具有指向对象成员的指针,计算指向对象的指针 - C++ conversion: have pointer to object member, calculate pointer to object 在C ++中使用指针成员变量返回对象 - Returning an object with a pointer member variable in C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM