您通常不需要詳細瞭解Obj文件的內部格式,因爲它們是爲您生成的。所有你需要知道的是,對於你創建的每一個類,編譯器都會生成Obj文件,它是你的類的二進制字節碼,適合於你編譯的操作系統。然後,下一步 - 鏈接 - 將您的程序所需的所有類的目標文件放在一個EXE或DLL中(或其他任何非Windows OS-es的格式)。也可以是EXE +幾個DLL,這取決於你的意願。
最重要的是你分開你的類的接口(聲明)和實現(定義)。
總是隻放在你的類的頭文件接口聲明。沒有別的 - 這裏沒有實現。避免使用自定義類型的成員變量,這些類型不是指針,因爲對於它們來說,前向聲明是不夠的,你需要在頭文件中包含其他頭文件。如果你的標題包含了,那麼設計就會有氣味,並且會減慢構建過程。
類方法或其他函數的所有實現應該在CPP文件中。這將保證當有人包含您的頭文件時,編譯器生成的Obj文件將不再需要,並且您只能從CPP文件中包含其他文件。
但爲什麼要麻煩?答案是,如果你有這樣的分隔,那麼鏈接速度會更快,因爲每個類都使用了每個Obj文件。另外,如果你改變了你的類,這將在下一次構建時改變其他一些對象文件。
如果你在頭文件中包含了,這意味着當編譯器爲你的類生成Obj文件時,它應該首先爲你的頭文件中包含的其他類生成Obj文件,這可能需要其他Obj文件等等。甚至可能是循環依賴,然後你不能編譯!或者如果你改變了你的類中的某些東西,那麼編譯器將需要重新生成許多其他的Obj文件,因爲如果你沒有分離,它們會在一段時間後變得非常緊密依賴。
我不認爲看對象文件將有助於理解你提到的觀點。思考「編譯器需要知道如何爲這個輸入創建機器代碼」這個問題可能更有用?例如,要將'A * a'傳遞給下一個函數,編譯器不需要知道A是什麼樣子,而是調用'a-> foo()',它就是這樣。從「A」派生,至少需要知道「A」的大小和所有方法簽名。 – 2010-07-09 07:46:04
嗨克里斯托弗,我同意你的觀點。事實上,這就是我想從哪裏開始。但是,即使像「從A派生出來的東西,至少需要知道A的大小」對我來說也不是那麼明顯。爲什麼不能將A的大小知識推遲到說出運行時間,或者說在鏈接時間,而不是在創建目標文件時的編譯時間。因此,我得出結論,我可能需要從不同的角度理解編譯器在目標文件中放置什麼信息。 – xyz 2010-07-09 07:54:45
我認爲Stanley B Lippman的書:「C++內部對象模型」可以幫助你理解一些主題 – 2010-07-09 08:50:04