c ++处理跨超级/基类的函数指针

时间:2015-10-23 23:02:36

标签: c++ function-pointers

我有一个模板定义的类来处理所有不同方法的处理。这些方法各不相同,或者可以根据执行的执行类型进行分组。所以我将继承超类处理属性,但定义了需要处理的所有不同方法。 我有函数指针不匹配错误。任何人都可以为这个问题提出解决方案

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

再次抱歉无法添加完整的代码。

1 个答案:

答案 0 :(得分:2)

这不是类型安全的,因为你有一个(隐藏的)协变参数。

实际函数Type_Injection::TypeFunction1需要类型为this的{​​{1}}参数。但是呼叫站点只提供Type_Injection而不是后者的每个实例都是前者之一。

实际参数可能总是更多派生类型,在这种情况下,您可以使用强制转换来覆盖编译器类型检查。但我只会使用Injection<enum_defined_for_type>,并在向地图添加回调时使用std::function<void (call_status_s*)>来指定目标对象(假设目标对象始终是持有地图的类实例,并且不会改变在通话时间)。

std::bind

在您的特定情况下,另一个选项就是使您的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*语句将switch值映射到派生类中的函数。这是非常有效的,完全类型安全的,并且当值不匹配/未知时可以委托给基类,以允许在类层次结构的不同级别中实现不同的行为。与地图不同,这只允许查找,因此如果需要迭代,T_ENUM的地图将是更好的选择。

另一个选项是“奇怪的重复模板模式”,它允许派生类通知基类对象的实际类型,以便映射可以包含std::function函数指针。但这消除了在调用树的多个级别提供行为的能力。