您可以尝试将runUserMethod 设为模板方法。此外,为了安全地将其从基类转换为派生类,您应该使用 dynamic_cast 所以基类必须是多态的(例如通过添加虚拟析构函数):
class Base {
public:
template <class T>
int runUserMethod( int (T::* pointer_to_method)()) {
T* p = dynamic_cast<T*> (this);
if (p == NULL) throw std::runtime_error("cast error");
// do some stuff before
int retval = (p->*pointer_to_method)();
// do some stuff after
return retval;
}
virtual ~Base() {};
};
函数用法与您的代码示例中的相同:
Base* b = new UserClass;
int r = b->runUserMethod(&User::user_method);
函数参数和返回类型也可以作为模板参数,以便 runUserMethod 接受其他函数签名:
class Base {
public:
// 0 arguments
template <class T, class R>
int runUserMethod( R (T::* pointer_to_method)()) {
T* p = dynamic_cast<T*> (this);
if (p == NULL) throw std::runtime_error("cast error");
// do some stuff before
R retval = (p->*pointer_to_method)();
// do some stuff after
return retval;
}
// 1 argument
template <class T, class R, class ARG1>
int runUserMethod( R (T::* pointer_to_method)(ARG1), ARG1 arg1) {
T* p = dynamic_cast<T*> (this);
if (p == NULL) throw std::runtime_error("cast error");
// do some stuff before
R retval = (p->*pointer_to_method)(arg1);
// do some stuff after
return retval;
}
// 2 arguments
// [...]
virtual ~Base() {};
};
这样下面的代码也可以工作:
class UserClass : public Base {
public:
int user_method1 (void) {return 0;}
float user_method2 (void) {return 0.0f;}
int user_method3 (int x) {return 0;}
};
int main(int argc, char* argv[]) {
Base* b = new UserClass;
int r1 = b->runUserMethod(&UserClass::user_method1);
float r2 = b->runUserMethod(&UserClass::user_method2);
int r3 = b->runUserMethod(&UserClass::user_method3, 2);
}