第一个: 我在某处读到虚拟函数的机制是未定义的。即这意味着每个编译器都可以以不同方式推进。但是,我发现的关于虚函数mechanisn的每一篇文章都谈到了VTBL和VPTR。虚拟函数机制实现
是否还有其他的虚拟功能机制实现?你能举一些例子吗?
second: 不同语言的VTBL实现有什么区别?
第一个: 我在某处读到虚拟函数的机制是未定义的。即这意味着每个编译器都可以以不同方式推进。但是,我发现的关于虚函数mechanisn的每一篇文章都谈到了VTBL和VPTR。虚拟函数机制实现
是否还有其他的虚拟功能机制实现?你能举一些例子吗?
second: 不同语言的VTBL实现有什么区别?
这可以帮助你:
Virtual method table: Comparison with alternatives
不同的编译器供应商可能会选择不同的方法......但最后的执行工作必须符合标准。这是本...
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf(10.3节)
我会告诉你一个例子。
class B
{
private:
int m_i;
public:
void foo() { puts("B::foo"); }
virtual void bar() { puts("B::bar"); }
};
class D : public B
{
private:
int m_j;
public:
virtual void bar() { puts("D::bar"); }
virtual void asdf() { puts("D::asdf"); }
};
int main()
{
D d;
B *pb = &d;
pb->bar();
}
大多数编译器实现了代码如下:
struct B;
struct __vtbl_B_t
{
void (*bar)(B * const this);
};
struct B
{
const __vtbl_B_t *__vptr;
int m_i;
};
void B__foo(B * const this) { puts("B::foo"); }
void B__bar(B * const this) { puts("B::bar"); }
const __vtbl_B_t __vtbl_B = { B__bar };
void B__ctor(B * const this)
{
this->__vptr = &__vtbl_B;
}
struct D;
struct __vtbl_D_t
{
__vtbl_B_t __base;
void (*asdf)(D * const this);
};
struct D
{
B __base;
int m_j;
};
void D__bar(D * const this) { puts("D::bar"); }
void D__asdf(D * const this) { puts("D::asdf"); }
__vtbl_D_t __vtbl_D = { { (void (*)(B * const))D__bar }, D__asdf };
void D__ctor(D * const this)
{
B__ctor((B * const)this);
this->__base.__vptr = (const __vtbl_B_t *)&__vtbl_D;
}
int main()
{
D d;
D__ctor(&d);
B *pb = (B *)&d;
(*pb->__vptr->bar)(pb);
}
输出:
D::bar
即使你的语言不是C++,编译器的行为是similiar。
一个受欢迎的选择是inline caching,我认为它来自于Smalltalk系统。
另一种选择是每个多态方法都有一个类型表,而不是每个类型都有一个多态方法表(VMT)。它需要完整的程序分析,但可以实现高效的多重继承。一些Eiffel编译器使用这种方法(more here,寻找“如何有效地实现多重继承?”)。
最后一个也提到了另一种方法,一个基于switch语句的方法(检查C中的Eiffel〜switch)。 SmartEiffel使用它的变体,它根据类ID进行二进制搜索。它还需要进行全面的程序分析,但由于更好的指令缓存行为,有时在当前系统上可能比VMT更有效。 (more here,查找“无虚拟函数表的高效动态分派”)。