0

可能重复:
C++:访问虚拟方法

我正在尝试使用虚拟方法表通过类中的索引调用函数......假设我们有以下代码:

class Base
{
public:
    Base() {}
    virtual ~Base() {}

    virtual Base* call_func(unsigned int func_number)
    {
       // Some way to call f_n
    }
protected:
    virtual Base* f_1() const = 0;
    virtual Base* f_2() const = 0;
    virtual Base* f_3() const = 0;
};

我已经使用函数数组、if-statement 和 case-statement 实现了这一点……那么,是否有更好的方法来仅使用指针(例如访问 vtable)或类似的东西来调用方法?

解决此问题后,我将使用 f_1、f_2、f_3 的不同实现创建派生类(例如派生类 1 和派生类 2),并具有如下所示的类控件:

class Control
{
protected:
    Base* current;

public:
    Control(Base* curr = new derived1): current(curr) {}
    virtual ~Control() 
    {
        delete current;
    }
    virtual void call_functions(unsigned int func_numb)
    {
        delete current
        Base* new = current->call_func(func_numb);
        current = new;
    }
};

对不起我糟糕的英语:S ...并提前感谢!

4

3 回答 3

1

C++ 没有很好的内置自省功能,也就是说,您可能知道,您不能在运行时按名称查找成员函数并从命名查找中调用它。但是你可以创建一个成员函数指针表;例如,请参阅 C++ FAQ Lite 条目中的示例如何创建和使用指向成员函数的指针数组?. (我希望这与您已经提到的“函数数组”不同,但它似乎确实是实现您想要的最佳方式。)

如果我可能会问,为什么需要按索引调用函数?虚函数通常存在以使用它们自己的一组任务参数来完成特定任务。

如果您要更直接地访问 vtable,您可能会做一些工作,但它会很脆弱且不可移植。

于 2012-12-12T15:03:50.210 回答
0

只是一个粗略的代码。

void *vptr = *(void**)this;
void *method = ((void**)vptr)[index + first_method_offset];
typedef void (*method_type)();
void *m = (method_type)method;
m();

如果您的索引方法不是 vtable 中的第一个,则需要 first_method_offset 。

于 2012-12-12T15:00:20.517 回答
0

Use pointer to member functions:

virtual Base* call_func(Base *(Base::*pf)())
{
  return this->*pf();
}

If you need the argument to be an arithmetic scalar, use a lookup array:

virtual Base* call_func(unsigned int func_number)
{
  static const Base *(Base::*(table[]))() = { &Base::f_1, &Base::f_2, &Base::f_3 };
  return this->*(table[func_number])();
}
于 2012-12-12T14:57:21.750 回答