2016-11-19 85 views
2

在下面的代碼段給我錯誤如果vtable是在編譯時創建的,爲什麼這個錯誤是鏈接器錯誤而不是編譯錯誤?

未定義參考`虛表爲衍生」

代碼:

#include <iostream> 
class base{ 
    public: 
    base(){} 
    virtual ~base(){} 
    virtual void test() 
    { 
    } 
}; 
class Derived:public base{ 
    public: 
    Derived(){} 
    ~Derived(){} 
    void test(); 
}; 
int main() { 
    base* b = new Derived(); 
    delete b; 
} 

我理解是因爲虛擬溫控功能testclass Derived中聲明但未定義。

但是當我g++ -c file.cpp編譯其按thisçompile或彙編源文件,但不鏈接。它不會給我任何錯誤並編譯好。因此,上述錯誤產生於鏈接時間而不是編譯時間。 從我學到的不是在編譯時創建的vtable。那爲什麼我在編譯時本身沒有得到這個錯誤呢?

+0

錯誤來自鏈接程序,因爲時間的檢查會顯示給您。 – EJP

+0

@EJP是的,我確實意識到這一點,並且對問題本身進行了描述。但我不明白的是,我不應該在編譯時自己gettng而不是鏈接。 – Hummingbird

+2

「編譯時」的描述包括鏈接時間,但不包括運行時 –

回答

2

但是,您認爲在編譯時必須創建一個vtable,這是錯誤的。

單獨編譯是標準中的核心概念。這是編譯單元(又名源文件)可以編譯的原因,只要它聲明瞭所需的函數即使它沒有定義的可見性。

在典型的「編譯然後鏈接」構建鏈中,這允許編譯單元(源文件)進行編譯,給定任何可能在另一編譯單元中定義的函數聲明(成員函數或非函數)。

接下來需要檢測到函數定義的缺失。

實際上,這意味着編譯器可能會發出有關vtable的信息,但它會是鏈接器(ahem)將vtable的規範鏈接到實際的成員函數。

+0

謝謝..現在我想我明白它...和vtable部分我從[這裏]參考(http://stackoverflow.com/questions/3849498/當-vtable-in-c-created) – Hummingbird

+0

該鏈接只是說,創建的vtable是由實現來處理的。它並沒有說它只在編譯期間發生。在「編譯然後鏈接」工具鏈中,鏈接器是實現的一個組件。 – Peter

+0

我同意你的觀點,雖然鏈接確實說引用** vtables是在編譯時創建的結構**反正這讓我感到困惑。 – Hummingbird

2

我能得到什麼用g++ foo.cpp -v

/tmp/ccBc4VPu.o: In function `Derived::Derived()': 
foo.cpp:(.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev]+0x1f): undefined reference to `vtable for Derived' 
collect2: error: ld returned 1 exit status 

這是一個連接錯誤,而不是一個編譯器錯誤本身。

錯誤的根本原因是在Derived中聲明瞭test,但未實際執行。鏈接器提供了一個令人困惑的錯誤消息。應宣佈一個錯誤失蹤Derived::test方法

+0

這就是爲什麼這是鏈接器錯誤的確切問題?從我學到的vtable是在編譯時創建的?所以很好理解爲什麼我在編譯時本身並沒有在連接的時候得到錯誤。 – Hummingbird

1

GCC有針對此問題的FAQ entry

當建立C++中,連接說我的構造函數,析構函數或虛表是不確定的,但我定義它們

解決方案是確保所有非純的虛擬方法都已定義。請注意,即使聲明爲純虛擬[class.dtor]/7,也必須定義析構函數。

+0

謝謝,我明白這一點,但我無法理解的是,「如果vtable是在編譯時創建的,那麼爲什麼我不會得到這個錯誤也只是編譯時間,而是在連接時間。」如果那不是太多問。 – Hummingbird

+1

@DevanshMohanKaushik vtable由編譯器分配並由鏈接器初始化。看起來像彼得斯詳細描述了這一點。 – Nikita

+0

是的,那是什麼我感到困惑..謝謝不管怎樣 – Hummingbird

2

編譯器不需要有所有可用的方法。他有足夠的聲明。

該方法可以在不同的編譯單元(cpp/cxx文件)中實現,因此編譯器甚至不可能檢查此方法是否可用。編譯器在處理一個cpp文件。

這是連接器的工作,以匹配方法和調用。