简体   繁体   中英

Generic Function pointer to the class member function

How can I have generic function pointer. Consider following class.

#ifndef PERSON_HPP_
#define PERSON_HPP_

#include <string>

class Person {
public:
  Person() {
  }
  void SetName(std::string person_name) {
    m_name = person_name;
  }
  void setDept(std::string dept_name) {
    m_dept = dept_name;
  }
  void setAge(int person_age ) {
    m_age = person_age;
  }
  std::string getName() {
    return m_name;
  }
  std::string getDept() {
    return m_dept;
  }
  int getAge() {
    return m_age;
  }
private:
  std::string m_name;
  std::string m_dept;
  int m_age;
};

#endif

I want to store the function pointers in a std::vector for setName , setDept , constructor and so on ...

For normal function I could achieve this using following

#include <vector>


int mult(int a) { 
  return 2*a; 
}

int main()
{
    int b;

    std::vector<void *(*)(void *)> v;
    v.push_back((void *(*)(void *))mult);
    b = ((int (*)(int)) v[0])(2);        // The value of b is 2.

    return 0;
}

No Boost allowed in my case.

You can write:

// Pointer to member function as a data type. 
typedef void (Person::*MethodPtr)(std::string); 
std::vector<MethodPtr> v;

Pointers to members are not any way different from any other data types. Only it should be used as binary operator:

Person *bad_guy = ...;
bad_guy->*v[4]("abcd");

It seems that you want to avoid the re-writing the getter/setter method, which typically have similar code inside.
However, it's a bad idea to use function pointer for such task because it reduces readability, adds complexity and doesn't allow the compiler to do the optimizations related to inlining .

If you want to automate the code generation for using getter/setter then use editor which has facility to generate getter/setter such as eclipse or you can resort to macros in this case:

#define SETTER(TYPE,FIELD) \
  set##FIELD (const TYPE FIELD) \
  { \
    this->m_##FIELD = FIELD; \
  }
#define GETTER(FIELD) \
  get##FIELD () const \
  { \
    return this->m_##FIELD; \
  }

And use it as,

class Person {
public:
  Person() {
  }
  void SETTER(std::string, name);
  void SETTER(std::string, dept);
  void SETTER(int, age);

  int GETTER(name);
  int GETTER(dept);
  int GETTER(age);

private:
  std::string m_name;
  std::string m_dept;
  int m_age;
};

#undef SETTER
#undef GETTER

If you really need to cast the member pointers to a common type (like void*), you can do:

template <typename T>
void* castToVoidStar(T x) {
  return *reinterpret_cast<void**>(&x);
}

void *afterCast = castToVoidStar(&Person::getName)

However, I do not believe it is wise to do so. C++ has type safety for a reason.

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