【问题标题】:Member function pointer of template class模板类的成员函数指针
【发布时间】:2015-02-25 01:42:22
【问题描述】:

假设我有一个类myClass 定义如下:

template<typename Type> class myClass {

    public:

        Type* pParent;
        void (Type::*func_exe) ();

        void execute();

};

我想用它作为函数fGiveMeYourClass的参数,它用它来调用它的成员函数execute

void fGiveMeYourClass ( ?myClass? ){

    ..?.. ->execute();

}

因为我不关心 Type 在这个模板中实际上是什么并且只想要这个类的成员函数指针,所以我可以使用 typedef 之类的东西来接受该成员函数指针fGiveMeYourClass的参数

我已经尝试过了,但我的尝试似乎失败了:

template <typename Type> typedef void(myClass<Type>::*pMyClassExec)();
void fGiveMeYourClass(pMyClassExec pointerToMemberFunction);

还有其他方法可以实现还是我做错了什么?

【问题讨论】:

  • 为什么不只是template &lt;typename T&gt; void fGiveMeYourClass(myClass&lt;T&gt; const &amp; x){ x.execute(); }?目前还不清楚函数指针应该从哪里进来。
  • 好吧,我知道我可以模板化整个函数,但由于这个类被用作许多其他函数的参数,这意味着将它们全部转换为模板,这看起来不是最干净的解决方案对我来说。我认为可能有一种更简单的方法......特别是因为我只关心该类的一个成员函数,无论Type 是什么,它的工作方式都是一样的。
  • 您可以将execute 声明为非模板基类中的虚函数,并传递指向基类的指针/引用。
  • 确实有效 :) 非常感谢!我已经在here 上找到了这种方法,但我不确定它如何或是否对我有用……我想我得再看看that 的 C++ 部分……那个我跳过了,因为我认为现在学习它对我没有帮助:D

标签: c++ templates member-function-pointers


【解决方案1】:

感谢Alan Stokes 他在我的问题上发表的评论:

您可以在非模板基类中将 execute 声明为虚函数,并传递指向基类的指针/引用

这解决了我的问题。

如果有人感兴趣: 我需要这个来实现一个可以传递给我的游戏引擎的一部分的类,以让引擎在给定的事件中自动执行一段自定义代码(测试函数?),例如当用户在游戏中按下“调试测试功能”按钮时。然而,它也有许多其他应用程序

这是我目前用于这些打包命令的代码:

class VE_COMMAND_PABA;
class VE_STANDARD_COMMAND;
template <typename ReturnValueType, typename Param1Type, typename Param2Type> class VE_FUNC_COMMAND;
template <typename ParentClassType, typename ReturnValueType, typename Param1Type, typename Param2Type> class VE_DERIVED_FUNC_COMMAND;

class VE_COMMAND_PABA {

    public:

        enum VE_COMMAND_TYPE {

            VE_CT_STANDARD,
            VE_CT_FUNC,
            VE_CT_DERIVED

        } paba_type;

        virtual void execute() = 0;
        virtual void Release() = 0;

};

class VE_STANDARD_COMMAND : public VE_COMMAND_PABA {

    private:


    public:

        enum VE_STANDARD_COMMAND_TYPE {

            VE_SCT_BOOL_TOGGLE,
            VE_SCT_INCREMENT,
            VE_SCT_DECREMENT,
            VE_SCT_SET_INT,
            VE_SCT_SET_FLOAT,
            VE_SCT_SET_BOOL

        } type;

        bool* pBOOL;
        int* pINT;
        float* pFLOAT;

        bool params_allocated;

        int* set_int;
        float* set_float;
        bool* set_bool;

        VE_COMMAND_PABA* command_exe; // <- REFERENCE TO BASE CLASS

        void execute();

        void Release(){

            if(this->command_exe != nullptr) this->command_exe->Release();

            if(this->type == VE_SCT_SET_BOOL && this->params_allocated) delete this->set_bool;
            if(this->type == VE_SCT_SET_FLOAT && this->params_allocated) delete this->set_float;
            if(this->type == VE_SCT_SET_INT && this->params_allocated) delete this->set_int;

            delete this; // bye bye ...

        };

};

template <typename ReturnValueType, typename Param1Type, typename Param2Type> class VE_FUNC_COMMAND : public VE_COMMAND_PABA {

    public:

        enum VE_FUNC_COMMAND_TYPE {

            VE_FCT_FUNC,
            VE_FCT_FUNC_PARAM,
            VE_FCT_FUNC_TWO_PARAM,

        } type;

        Param1Type* pParam1;
        Param2Type* pParam2;

        Param1Type** lpParam1;
        Param2Type** lpParam2;

        bool params_allocated;

        ReturnValueType (*func_exe) ();
        ReturnValueType (*func_param_exe) (Param1Type parameter);
        ReturnValueType (*func_two_param_exe) (Param1Type parameter1, Param2Type parameter2);

        void Release(){

            if(params_allocated){

                if(pParam1 != nullptr) free(pParam1);
                if(pParam2 != nullptr) free(pParam2);

            }

            if(this->command_exe != nullptr) this->command_exe->Release();

            delete this; // bye bye...

        };

        VE_COMMAND_PABA* command_exe; // <- REFERENCE TO BASE CLASS

        void execute(){

            switch(this->type){

                case VE_FCT_FUNC:
                    this->func_exe();
                    break;

                case VE_FCT_FUNC_PARAM:
                    this->func_param_exe((*(this->pParam1)));
                    break;

                case VE_FCT_FUNC_TWO_PARAM:
                    this->func_two_param_exe((*(this->pParam1)), (*(this->pParam2)));
                    break;

                default:
                    DebugBreak();
                    break;

            };

            if(this->command_exe != nullptr){

                this->command_exe->execute();

            }

        };

};

template <typename ParentClassType, typename ReturnValueType, typename Param1Type, typename Param2Type> class VE_DERIVED_FUNC_COMMAND : public VE_COMMAND_PABA {

    public:

        enum VE_DERIVED_FUNC_COMMAND_TYPE {

            VE_DFCT_FUNC,
            VE_DFCT_FUNC_PARAM,
            VE_DFCT_FUNC_TWO_PARAM,

        } type;

        Param1Type* pParam1;
        Param2Type* pParam2;

        Param1Type** lpParam1;
        Param2Type** lpParam2;

        bool params_allocated;

        ParentClassType* pParent;
        ParentClassType** lpParent;
        ReturnValueType (ParentClassType::*child_func_exe) ();
        ReturnValueType (ParentClassType::*child_param_exe) (Param1Type parameter);
        ReturnValueType (ParentClassType::*child_func_two_param_exe) (Param1Type parameter1, Param2Type parameter2);

        void Release(){

            if(params_allocated){

                if(pParam1 != nullptr) free(pParam1);
                if(pParam2 != nullptr) free(pParam2);

            }

            if(this->command_exe != nullptr) this->command_exe->Release();

            delete this; // bye bye ...

        };

        VE_COMMAND_PABA* command_exe; // <- REFERENCE TO BASE CLASS

        void execute(){

            switch(this->type){

                case VE_DFCT_FUNC:
                    if(this->pParent != nullptr){

                        (this->pParent->*this->child_func_exe)();

                    }else{

                        ((*(this->lpParent))->*this->child_func_exe)();

                    }
                    break;

                case VE_DFCT_FUNC_PARAM:
                    if(this->pParent != nullptr){

                        (this->pParent->*this->child_param_exe)((*(this->pParam1)));

                    }else{

                        ((*(this->lpParent))->*this->child_param_exe)((*(this->pParam1)));

                    }
                    break;

                case VE_DFCT_FUNC_TWO_PARAM:
                    if(this->pParent != nullptr){

                        (this->pParent->*this->child_func_two_param_exe)((*(this->pParam1)), (*(this->pParam2)));

                    }else{

                        ((*(this->lpParent))->*this->child_func_two_param_exe)((*(this->pParam1)), (*(this->pParam2)));

                    }
                    break;

                default:
                    DebugBreak();
                    break;

            };

            if(this->command_exe != nullptr){

                this->command_exe->execute();

            }

        };

};

【讨论】:

    【解决方案2】:

    这可能很复杂,但我认为您正在尝试实现/实验以下内容:

    template <typename Type> 
    using Func = void (myClass<Type>::*)();
    
    
    template <typename Type> 
    void fGiveMeYourClass(Func<Type> fptr )
    {
    
    }
    

    如果我理解正确,最简单明了的方法是让你的成员函数指针工作:

    template <typename Type> 
    void fGiveMeYourClass(const myClass<Type>& x)
    { 
       (x.*x.func_exe)(); 
    }
    

    【讨论】:

    • 好吧,基本上是的,但我忘了提到我不想模板化fGiveMeYourClass(因为它使生成的代码看起来不干净,并迫使我使用该类模板化所有内容我想要的是一个指向其成员函数之一的指针)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 2012-07-05
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    相关资源
    最近更新 更多