c++ 跨 super/base class 处理函数指针
c++ handling function pointer across super/base class
我定义了一个模板 class 来处理所有不同方法的处理。这些方法各不相同,或者可以根据我正在执行的执行类型进行分组。所以我将继承 super class 处理属性,但定义所有需要处理的不同方法。
我有函数指针不匹配错误。谁能针对这个问题提出解决方案
template <class T_ENUM>
class Injection
{
public:
Injection();
~Injection();
virtual void addAllCalls( void );
bool addCall( T_ENUM );
protected:
void* data; // drive of device under test
struct call_info {
T_ENUM call_ref;
string time_stamp;
};
// class specific function pointer defenition
// call_status_s is defined struct
typedef void (Injection::*funcType)(call_status_s*);
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
// here i process the function pointer based on the T_ENUM
bool processCall ( T_ENUM );
virtual void initCallMap( void );
// initialise the functions taken from child class and store here
};
class Type_Injection : public Injection<enum_defined_for_Type> {
public:
void addAllCalls( void );
private:
void initCallMap ( void );
// would initialise func_call_map with the functions pointer of TypeFunction1
// this is the function im going to save as pointers in the list defined in super class
void TypeFunction1 ( call_status_s* );
};
编译错误:
error: cannot convert ‘void (Type_Injection::*)(call_status_s*)’ to
‘void (Injection<enum_defined_for_Type>::*)(call_status_s*)’ in
assignment
再次抱歉无法添加完整代码。
这不是类型安全的,因为你有一个(隐藏的)协变参数。
实际函数 Type_Injection::TypeFunction1
需要类型 Type_Injection
的 this
参数。但是调用站点只提供了一个 Injection<enum_defined_for_type>
而不是后者的每个实例实际上都是前者之一。
可能实际参数始终是更派生的类型,在这种情况下,您可以使用强制转换来覆盖编译器类型检查。但我只会使用 std::function<void (call_status_s*)>
来代替,并在将回调添加到地图时使用 std::bind
来指定目标对象(假设目标对象始终是持有地图的 class 实例,并且在通话时间不会变化)。
typedef std::function<void (call_status_s*)> funcType;
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
void Type_Injection::initCallMap ( void ) override
{
using std::placeholders::_1;
func_call_map[T_ENUM_FUNCTION1] = std::bind(&Type_Injection::TypeFunction1, this, _1);
}
在您的特定情况下,另一种选择是让您的 processCall
函数接受 T_ENUM
选择器 virtual
(它不应该也接受 call_status_s*
函数参数传递给被调用的函数?)。在派生 class 中,您可以使用 switch
语句将 T_ENUM
值映射到派生 class 中的函数。这是非常有效的,完全类型安全的,并且可以在值 match/isn 未知时委托给基础 class,以允许在 [=37= 的不同级别实现不同的行为] 等级制度。与地图不同,这只允许查找,因此如果需要迭代,std::function
的地图将是更好的选择。
另一个选项是 "Curiously Recurring Template Pattern",它允许派生 class 将对象的真实类型告知基 class,以便映射可以包含 void (DerivedType::*)(call_status_s*)
函数指针。但这消除了在调用树的多个级别提供行为的能力。
我定义了一个模板 class 来处理所有不同方法的处理。这些方法各不相同,或者可以根据我正在执行的执行类型进行分组。所以我将继承 super class 处理属性,但定义所有需要处理的不同方法。 我有函数指针不匹配错误。谁能针对这个问题提出解决方案
template <class T_ENUM>
class Injection
{
public:
Injection();
~Injection();
virtual void addAllCalls( void );
bool addCall( T_ENUM );
protected:
void* data; // drive of device under test
struct call_info {
T_ENUM call_ref;
string time_stamp;
};
// class specific function pointer defenition
// call_status_s is defined struct
typedef void (Injection::*funcType)(call_status_s*);
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
// here i process the function pointer based on the T_ENUM
bool processCall ( T_ENUM );
virtual void initCallMap( void );
// initialise the functions taken from child class and store here
};
class Type_Injection : public Injection<enum_defined_for_Type> {
public:
void addAllCalls( void );
private:
void initCallMap ( void );
// would initialise func_call_map with the functions pointer of TypeFunction1
// this is the function im going to save as pointers in the list defined in super class
void TypeFunction1 ( call_status_s* );
};
编译错误:
error: cannot convert ‘void (Type_Injection::*)(call_status_s*)’ to
‘void (Injection<enum_defined_for_Type>::*)(call_status_s*)’ in
assignment
再次抱歉无法添加完整代码。
这不是类型安全的,因为你有一个(隐藏的)协变参数。
实际函数 Type_Injection::TypeFunction1
需要类型 Type_Injection
的 this
参数。但是调用站点只提供了一个 Injection<enum_defined_for_type>
而不是后者的每个实例实际上都是前者之一。
可能实际参数始终是更派生的类型,在这种情况下,您可以使用强制转换来覆盖编译器类型检查。但我只会使用 std::function<void (call_status_s*)>
来代替,并在将回调添加到地图时使用 std::bind
来指定目标对象(假设目标对象始终是持有地图的 class 实例,并且在通话时间不会变化)。
typedef std::function<void (call_status_s*)> funcType;
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
void Type_Injection::initCallMap ( void ) override
{
using std::placeholders::_1;
func_call_map[T_ENUM_FUNCTION1] = std::bind(&Type_Injection::TypeFunction1, this, _1);
}
在您的特定情况下,另一种选择是让您的 processCall
函数接受 T_ENUM
选择器 virtual
(它不应该也接受 call_status_s*
函数参数传递给被调用的函数?)。在派生 class 中,您可以使用 switch
语句将 T_ENUM
值映射到派生 class 中的函数。这是非常有效的,完全类型安全的,并且可以在值 match/isn 未知时委托给基础 class,以允许在 [=37= 的不同级别实现不同的行为] 等级制度。与地图不同,这只允许查找,因此如果需要迭代,std::function
的地图将是更好的选择。
另一个选项是 "Curiously Recurring Template Pattern",它允许派生 class 将对象的真实类型告知基 class,以便映射可以包含 void (DerivedType::*)(call_status_s*)
函数指针。但这消除了在调用树的多个级别提供行为的能力。