我正在尝试使用虚方法表来通过索引来调用函数 一类......假设我们有以下代码:
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;
}
};
答案 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