2014-04-04 113 views
1

第一個: 我在某處讀到虛擬函數的機制是未定義的。即這意味着每個編譯器都可以以不同方式推進。但是,我發現的關於虛函數mechanisn的每一篇文章都談到了VTBL和VPTR。虛擬函數機制實現

是否還有其他的虛擬功能機制實現?你能舉一些例子嗎?

second: 不同語言的VTBL實現有什麼區別?

回答

0

我會告訴你一個例子。

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。

1

一個受歡迎的選擇是inline caching,我認爲它來自於Smalltalk系統。

另一種選擇是每個多態方法都有一個類型表,而不是每個類型都有一個多態方法表(VMT)。它需要完整的程序分析,但可以實現高效的多重繼承。一些Eiffel編譯器使用這種方法(more here,尋找「如何有效地實現多重繼承?」)。

最後一個也提到了另一種方法,一個基於switch語句的方法(檢查C中的Eiffel〜switch)。 SmartEiffel使用它的變體,它根據類ID進行二進制搜索。它還需要進行全面的程序分析,但由於更好的指令緩存行爲,有時在當前系統上可能比VMT更有效。 (more here,查找「無虛擬函數表的高效動態分派」)。