3

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

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)或类似的东西来调用方法?

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

编辑:感谢所有建议!我将扩展我的问题:

解决此问题后,我将使用 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 do_something(unsigned int func_numb)
    {
        delete current
        Base* new = current->next_state(stl);
        current = new;
    }
};
4

4 回答 4

1

要么是 switch 语句:

switch (func_number)
{
    case 1:
        f_1();
        break;
    case 2:
        f_2();
        break;
    case 3:
        f_3();
        break;
}

或者使用函数指针数组。

于 2012-12-12T13:54:25.057 回答
1

我假设您只想找到所有可能的方法来解决它。

您可以使用指向成员函数的指针映射(或向量)并将它们初始化一次(在构造函数中或静态地)。这可以模拟 vtable。

这几行之间的东西:

class Base
{
public:
    Base() {
        functions.insert(std::make_pair(1,&Base::f_1));
        functions.insert(std::make_pair(2,&Base::f_2));
        functions.insert(std::make_pair(3,&Base::f_3));
        }
    virtual ~Base() {}
    virtual Base* call_func(unsigned int func_number)
    {
    return (this->*functions[func_number])();
}
protected:
    std::map<unsigned int, Base*(Base:: *)()const> functions;
virtual Base* f_1() const = 0;
virtual Base* f_2() const = 0;
virtual Base* f_3() const = 0;

};

这甚至对于继承的类也应该有效(call_func不过我会做非虚拟的)。是的,您应该检查该项目是否真的在地图(或矢量)中,如果它不是nullptr.

于 2012-12-12T14:56:31.157 回答
1

没有可移植的方式来访问虚函数表;语言规范没有指定应该如何实现虚拟分派,因此甚至不需要表存在,更不用说程序可以访问了。

没有比您提到的方法更好的方法来做您想做的事情:函数指针表或if/switch条件。

于 2012-12-12T14:13:15.740 回答
0

注意 1:使用方法映射或 switch-case 方法访问您的方法比使用 vtable 指针更安全。

注意 2:小程序集部分适用于 VC++,不确定是否适用于其他编译器。

虽然存在一种访问虚拟表函数的方法:

// create our object
X *obj = new X();

// access the vtable pointer
int* vptr = *(int**)obj;

// set the this pointer
__asm
{
  mov ecx, obj
}

// call the first method from the vtable
( (void (*)()) vptr[0] )();

请参阅此处的深入解释:http: //kaisar-haque.blogspot.nl/2008/07/c-accessing-virtual-table.html

于 2012-12-12T15:08:34.720 回答