C++ C++;:访问虚拟方法

C++ C++;:访问虚拟方法,c++,pointers,methods,virtual,vtable,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; vir

我正在尝试使用虚拟方法表通过索引在中调用函数 一个班级。。。假设我们有以下代码:

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语句实现了这个 案例陈述。。。那么,有没有更好的方法来调用方法呢 只使用指针(例如访问vtable)或类似的东西

对不起,我的英语糟透了。。。提前谢谢你

编辑: 谢谢你的建议!我将扩展我的问题:

解决这个问题后,我将创建派生类(例如derived1和derived2) 使用不同的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;
    }
};

switch语句:

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

或者使用函数指针数组。

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


没有比您提到的方法更好的方法了:函数指针表,或
if
/
开关
条件。

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

您可以使用指向成员函数的指针的映射(或向量)并初始化它们一次(在构造函数中或静态地)。可以模拟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;
类基
{
公众:
Base(){
insert(std::make_pair(1,&Base::f_1));
insert(std::make_pair(2,&Base::f_2));
insert(std::make_pair(3,&Base::f_3));
}
虚拟~Base(){}
虚基*调用函数(无符号整数函数号)
{
返回(this->*函数[func_number])();
}
受保护的:
std::map函数;
虚基*f_1()常数=0;
虚基*f_2()常数=0;
虚基*f_3()常数=0;
})

即使对于继承的类,这也应该起作用(不过,我会将
call\u func
设置为非虚拟的)。
是的,您应该检查该项是否真的在映射(或向量)中,以及它是否不是
nullptr

注1:使用方法映射或切换案例方法访问您的方法比使用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] )();
请参阅此处的详细说明:

你想让“call_func”成为虚拟的吗?好问题。我同意,感觉应该有一种方法可以使用
func_number
直接索引到我们知道已经存在的指针表中(在所有常见的实现中)。遗憾的是,我认为没有
if
switch
是唯一的选择,因为您需要虚拟调用。@NicholasWilson:问题是它只存在于“所有常见实现”中,而不是所有可能的实现中。语言规范不要求它在那里,因此没有可移植的方式来访问它!所以你最好了解你的目标平台。对不起,当我说案例陈述时,我想说的是切换-statement@gvo:啊,我在你的问题中漏掉了。无论如何,这可能是最好的办法。这里有点异味;如果你给我们一个更高层次的解释,我们可以给你一些更好的想法。好的:(谢谢,我想维基百科把我和他关于使用pseudo-c的虚拟方法表的文章搞混了++