C ++:访问虚拟方法

时间:2012-12-12 13:49:24

标签: c++ pointers methods virtual vtable

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

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 ...并提前致谢!

编辑: 谢谢你的所有建议!我要扩展我的问题:

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

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 个答案:

答案 0 :(得分:1)

切换声明:

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

或使用函数指针数组。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

我假设您只想找到解决问题的所有方法。

您可以使用指向成员函数的指针的map(或vector)并初始化它们(在构造函数中或静态地)。这可以模仿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

答案 3 :(得分: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