简体   繁体   中英

How to store a member function pointer through an interface

I would create an interface like that :

class IMother {
public:
  // This getter return a map which contains a member functer pointer
  virtual map<string, void (IMother::*)()> getMap() const = 0;
  virtual ~IModule() {};
};

Then, create a child and override the getter in order to return a map which contain only Child_1 member function pointer

class Child_1 : public IMother {
private:
  map<string, void (Child1::*)(int)> _map;

public:
  void do_something_1(int a) {
     // Something...
  }

  void do_something_2(int a) {
   // Something...
  }

  virtual map<string, void (Child1::*)(int)> getMap() {
     _map["do_1"] = &do_something_1;
     _map["do_2"] = &do_something_2;
     return _map;
  }

I thought I'll be able to make it work because, in my mind, I thought Child1 is a IMother so I have the right to write that but I cannot..

int main() {
   IMother *mother = new Child_1;

   // I don't know how run a method through a map
   mother->getMap["do_1"](42); // Not seem to work
   return 0;
}

Is there a way to store a member function pointer trough an interface ?

IMother::getMap and IChild::getMap have different return types. This is allowed only if those return types are covariant . Despite IMother and IChild are covariant, std::map<...IMother...> and std::map<...IChild..> are not. So your example cannot be compiled with error: invalid covariant return type

There are few issues here:

  1. Firstly assignment of pointer to members is incorrect:

    This:

     _map["do_1"] = &do_something_1; _map["do_2"] = &do_something_2; 

    Should be:

     _map["do_1"] = &Child1::do_something_1; _map["do_2"] = &Child1::do_something_2; 
  2. Second, the return types of getMap() on IMother and Child1 differ since one takes no params and a pointer to member of IMother and the other takes an int and is a pointer to member of Child1. Those two differences cause the return types to be different in C++.

    IMother:

     map<string, void (IMother::*)()> 

    Child1:

     map<string, void (Child1::*)(int)> 

    Since the return types are different Child1 has not overridden all the pure virtual functions defined in IMother, thus you cannot instantiate an instance of Child1.

  3. Third, your member function invocation is incorrect. Member functions still need the "member" supplied before invoking. eg

     class SomeClass; typedef void (SomeClass::* SomeClassFunction)(void); void Invoke(SomeClass *pClass, SomeClassFunction funcptr) { (pClass->*funcptr)(); }; 

That being said I would look at the stl functional header. stl functional lib will allow you to write the following and later invoke them in a much simpler syntax than the built in C++ syntax:

typedef std::function<float (float)> MyFuncType;

map<sting, MyFuncType> myFuncs;
myFuncs["myCustomSin"] = &SomeClass::SomeCustomSinFunc;
myFuncs["cSin"] = &sin;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM