第一個: 我在某處讀到虛擬函數的機制是未定義的。即這意味着每個編譯器都可以以不同方式推進。但是,我發現的關於虛函數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,查找「無虛擬函數表的高效動態分派」)。