(c++)如何指向子类中的方法
(C++) How to point to a method in a subclass?
我有一个基类Base
,它的方法是runUserMethod(void * pointer_to_method)
。
class Base {
int runUserMethod(METHTYPE pointer_to_method) {
// do some stuff before
int retval = pointer_to_method();
// do some stuff after
return retval;
}
};
现在,我想实现runUserMethod
,使其能够运行Base
子类实现的任何方法,只要这种方法遵循一些标准签名,如int <methodname> (void)
UserClass
类:
class UserClass : public Base {
int user_method (void);
};
METHTYPE
应该是什么,以便我可以做以下操作?
Base * b = new UserClass();
int retval = b->runUserMethod(&UserClass::user_method);
同样,它会工作吗?有更好的方法吗?基本上,我要做的是拦截子类方法调用的调用,以一种或多或少对用户透明的方式。
可以使用std::function
和std::bind
:
struct Base
{
typedef std::function<int()> METHTYPE;
int runUserMethod(METHTYPE pointer_to_method)
{
return pointer_to_method();
}
};
UserObject b;
auto func_object = std::bind(&UserObject::user_method, std::ref(b));
int retval = b.runUserMethod(func_object);
你可以尝试让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);
}
如果你改变你的例子在更真实可行的状态,你会看到这个问题:
int retval = (this->*methptr)();
撇开丑陋的语法不谈,问题是你需要传递具有Base *类型的"this"指针到方法调用,但你应该传递指针到派生类的方法
因此,您要么需要让runUserMethod意识到派生类(可能是通过模板),要么需要将指向派生方法的指针类型转换为指向基方法的指针,这有可能出现问题:
class Derived1 : public Base ...
class Derived2 : public Base ...
Derived2 d2;
d2.runUserMethod( static_cast<METHTYPE>( &Derived1::func ) ); // problem Derived2 * will be passed to Deriived1 method and there is no easy way to detect that
所以使用std::bind会更安全。你不需要从Base继承(我不知道这对你是否合适)
相关文章:
- 将子类方法声明为基类的友元
- 函数从唯一代码调用正确的子类方法
- 将"this"从父类方法转换为子类方法是一种好的做法吗?
- 从C++中的父类实例访问子类方法
- 基类中的虚拟方法和子类中的非 Virtula 方法.仍然如何调用子类方法,即使它是非虚拟的
- 按名称调用父级中的子类方法
- C++ - 如何使用基指针重写子类方法
- 如何在子类方法中更改参数
- 如何在尝试为某些非类型值实例化模板子类方法时产生编译器错误
- 访问指针数组中的子类方法
- 调用子类方法会导致分段错误
- 指向方法父参数c++的子类方法指针
- 函数调用父类方法而不是子类方法
- C++ 无法使用指向类的指针调用子类方法e
- 从SuperClass C调用子类方法
- 无法从 QML 访问C++ QObject 子类方法
- 使用继承接口的类的子类方法
- 如何迭代定义为超类的向量,但调用子类方法
- 在c++中从超类数组中访问子类方法
- 超类调用子类方法的STL迭代器