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_Injectionthis 参数。但是调用站点只提供了一个 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*) 函数指针。但这消除了在调用树的多个级别提供行为的能力。