感谢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();
}
};
};