2013-10-28 96 views
10

我(隱約地)知道模板沒有實例化,如果它是而不是使用。例如,即使T::typeT = int時沒有意義,以下代碼也可以很好地編譯。虛擬對類模板成員使用的影響

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 
}; 

A<int> a; //ok 

它編譯因爲f()不是使用,所以它不會被實例化—這樣的T::type有效性仍然選中。不要緊,如果其他一些成員函數g()調用f()

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    void g() { f(); } //Is f() still unused? 
}; 

A<int> a; //ok 

這也是compile fines。但在這裏,我意識到我對「使用」的定義的理解含糊不清。我問:

  • f()還未使用?究竟如何?

我可以清楚地看到它被用在g()裏面。但後來我認爲g()沒有使用,f()也沒有使用,從實例化的角度來看。這似乎夠合理。至今。

但是如果我添加virtual關鍵字g(),它不會編譯:

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    virtual void g() { f(); } //Now f() is used? How exactly? 
}; 

A<int> a; //error 

它導致compilation error因爲現在它嘗試實例f()。我不明白這種行爲。

有人能解釋一下嗎?特別是virtual關鍵字對類模板成員的「使用」定義的影響。

+1

如果我沒有記錯,'virtual'強制實例化成員函數,因爲現在幾乎不可能靜態評估是否使用該函數。在實踐中,你要求創建一個充滿指向函數指針的v表......所以函數需要存在,所以我們可以給它一個指針。 –

+0

結構模板只有在使用時纔會被實例化。它可能是整個結構或沒有。它與g或f沒有任何關係。 – Sarien

+1

@Sarien:它的確如此,模板類的成員函數只有在使用ODR的時候纔會被實例化。 –

回答

8

快速查看3.2 [basic.def.odr]產率:

3/[...]虛擬成員函數,如果它不是純ODR使用。 [...]

而且我也在14.7.1 [temp.inst]研究發現:

10 /的實現不應隱含實例化一個函數模板,成員模板,非虛擬成員函數,成員類或不需要實例化的類模板的靜態數據成員。 如果虛擬成員函數不會被實例化,則沒有指定實現是否隱式地實例化類模板的虛擬成員函數。(重點煤礦)

所以...我會說這很可能是一個virtual方法將總是被實例化。在實用術語中,我希望編譯器在實例化類時實例化模板類的虛擬表;並因此立即實例化該類的所有成員函數(因此它可以引用來自虛擬表的那些成員函數)。