補一點C++最最基礎的東西,翻譯自:stackoverflow的回答。
第一個回答
為了說清楚這個問題,首先要了解一些C和C++的基礎。
在編譯C/C++時,將源文件編譯為可執行文件實際上需要兩個步驟:編譯和鏈接。編譯一次接受一個.cpp文件並且編譯它,其它的.cpp文件對編譯器來說是不可見的,這會生成一個目標文件。然后,編譯器鏈接所有的目標文件以生成最終的可執行文件。
這在C++中引入了兩個重要的概念:聲明和定義。聲明指定一些東西(變量或函數)存在於某處。下面是函數Foo()的聲明:
1 void Foo();
這意味着我們告訴編譯器在某個地方將會有一個函數Foo(),這個函數沒有參數,也不返回任何值。
定義指定了這個函數的功能。下面是這個函數的定義:
1 void Foo() { cout<<"Foo!!"; }
接下來定義另一個函數Bar():
1 void Bar() { 2 Foo(); 3 cout<<"bar"; 4 }
這個函數調用了函數Foo()。如果函數foo之前沒有在同一個文件中進行聲明或定義,那么這個函數不能被編譯成功。因此聲明本身不產生任何編譯代碼,它們只需要待在那里。
如果函數Foo()沒有在此文件中進行定義,而是在另一個文件中進行了定義,那么鏈接器的作用就是在兩個函數之間建立鏈接。如果Foo()函數沒有在任何地方進行定義,那么就會得到一個鏈接錯誤,而不是一個編譯錯誤。
這就牽扯到頭文件的概念了,頭文件是存儲聲明的位置。當使用#include包含頭文件的內容時,實際發生的事情是預處理器(在實際編譯器之前執行的步驟)將加載包含的文件並將內容“粘貼”到原始源文件中。因此,編譯器將看到該文件,就好像整個頭文件實際上已粘貼到c ++文件中一樣。
因此,當使用C ++編程時,通常會將定義放在.cpp文件中,並將聲明放在.h文件中。
另一方面,命名空間只是一種對代碼進行邏輯分組的方式。
所以命名空間不存儲在單獨的文件中,並且它們沒有特定的文件擴展名。 如果我有一個具有多個命名空間的項目,我可能會為每個命名空間創建一個單獨的目錄(但是也有可能不會,它將取決於具體情況)。
第二個回答(轉自:路人甲JIA)
例如:你有一個向量類vector.h,則把它加入到project中。vector是標准庫STD中的一部分,因此可以使用以下語句來進入向量類:
1 std::vector
然而,如果程序員由於懶而不想在所有地方寫std::(標准庫有非常多有用的地方),則可以在.cpp文件的頂部寫:
1 using namespace std
這會告訴編譯器,每次它看到一個類型(比如向量)時,還要檢查命名空間std,因為定義可能在那里。這樣,就等價於以下聲明:
1 std::vector 2 vector
在vector.h中,會看到類似於下面的語句:
1 namespace std 2 { 3 class vector { /* Implementation */ } 4 }
因此,#include是用於添加文件,而using namespace用於保持代碼結構整潔干凈,並將其打包在“有意義”的庫中。當你編程時可以省略using namespace,但絕對需要使用#include。