用g++命令執行C++多檔案專案

2020-07-16 10:05:22
在不同的系統平台上,執行 C++ 程式的常用方式也有所不同。比如說在 Windows 平台上,我們經常使用 Visual Studio、dev C++、codeblocks 這些 IDE 執行 C++ 程式;而在 Linux 平台上,雖然也有很多可用的 C++ IDE,但執行 C++ 程式更常採用的方式是使用 g++ 命令。

除此之外,Linux 平台上還經常編寫 makefile 來執行規模較大的 C++ 專案。關於 makefile,讀者可閱讀《Makefile教學:Makefile檔案編寫1天入門》專題做詳細了解。

本節將在 CentOS 系統下(Linux 發行版之一),為讀者演示如何使用 g++ 命令執行 C++ 程式。

安裝g++編譯器

值得一提的是,CentOS 系統並沒有預設安裝 g++ 編譯器,需要我們自行安裝。讀者也可以使用如下命令驗證當前環境中是否已經安裝有 g++。

開啟 Terminal 終端並執行如下命令:

[[email protected] ~]# which g++
/usr/bin/g++

可以看到,我所使用的系統環境中,已經安裝好了 g++,其位於 /user/bin/g++ 目錄中。如果讀者所使用的系統環境中也已安裝好了 g++ 編譯器,可以跳過此安裝環節。

對於尚未安裝 g++ 編譯器的讀者,可直接在終端中執行如下命令:

yum install gcc-c++

注意,該命令執行時可能會提示“你需要以 root 許可權執行此命令”,這種情況下可以輸入su命令,然後輸入 root 使用者的登陸密碼,再次執行安裝指令即可成功安裝。

g++命令執行C++專案

《那些被編譯器隱藏了的過程》一節中講到,C 或者 C++ 程式的執行過程分為 4 步,依次是預處理、編譯、組合和連結。

我們知道,C++ 多檔案程式設計中有標頭檔案(.h 為字尾)和原始檔(.cpp為字尾)之分。需要注意的是,在執行 C++ 專案時,標頭檔案是不需要經歷以上這 4 個階段的,只有專案中的所有原始檔才必須經歷這 4 個階段。

假設有這樣一個 C++ 專案:
//student.h
class Student {
public:
    const char *name;
    int age;
    float score;
    void say();
};

//student.cpp
#include <iostream>   //std::cout、std::endl
#include "student.h"  //Student
void Student::say() {
    std::cout << name << "的年齡是" << age << ",成績是" << score << std::endl;
}

//main.cpp
#include "student.h"  //Student
int main() {
    Student *pStu = new Student;
    pStu->name = "小明";
    pStu->age = 15;
    pStu->score = 92.5f;
    pStu->say();
    delete pStu;  //刪除物件
    return 0;
}
該專案正確的執行結果為:

小明的年齡是15,成績是92.5


可以看到,當前專案中有 1 個 student.h 標頭檔案,student.cpp 和 main.cpp 2 個原始檔。接下來就用 g++ 命令執行此專案,其過程依次是:

1) 經歷預處理階段,執行如下命令:

[[email protected] ~]# g++ -E main.cpp -o main.i
[[email protected] ~]# g++ -E student.cpp -o student.i

其中,-E 選項用於限定 g++ 編譯器只進行預處理而不進行後續的 3 個階段;-o 選項用於指定生成檔案的名稱。Linux 系統中,通常用 ".i" 作為 C++ 程式預處理後所得檔案的字尾名。

感興趣的讀者可自行執行cat main.i指令檢視 main.i 檔案中的內容(student.i檔案也可以用此方式檢視)。


2) 經歷編譯階段,即對預處理階段得到的 -i 檔案做進一步的語法分析,生成相應的組合程式碼檔案。繼續執行如下命令:

[[email protected] ~]# g++ -S main.i -o main.s
[[email protected] ~]# g++ -S student.i -o student.s

其中,-S 選項用於限定 g++ 編譯器對指定檔案進行編譯,得到的組合程式碼檔案通常以“.s”作為字尾名。感興趣的讀者可以使用 cat 命令檢視生成檔案的內容。

3) 經歷組合階段,即將組合程式碼檔案轉換成可以執行的機器指令。繼續執行如下命令:

[[email protected] ~]# g++ -c main.s -o main.o
[[email protected] ~]# g++ -c student.s -o student.o

-c 指令用於限定 g++ 編譯器只進行組合操作,最終生成的目標檔案(本質就是二進位制檔案,但還無法執行)通常以“.o”作為字尾名。

4) 經歷連結階段,即將所有的目標檔案組織成一個可以執行的二進位制檔案。執行如下命令:

[[email protected] ~]# g++ main.o student.o -o student.exe

注意,如果不用 -o 指定可執行檔案的名稱,預設情況下會生成 a.out 可執行檔案。Linux 系統並不以檔案的擴充套件名開分割區檔案型別,所以 a.out 和 student.exe 都是可執行檔案,只是檔名稱有區別罷了。

以上 4 個階段中,檔案的生成不分先後,只要保證所有原始檔都得到處理即可。

經歷以上 4 步,最終會生成 student.exe 可執行檔案,其執行結果為:

[[email protected] ~]# ./student.exe
小明的年齡是15,成績是92.5

注意“./”表示當前目錄,不能省略。


讀者可能覺得整個執行過程非常繁瑣,直接執行如下命令即可生成最終的可執行檔案:

[[email protected] ~]# g++ main.cpp student.cpp -o student.exe
[[email protected] ~]# ./student.exe
小明的年齡是15,成績是92.5

強烈建議初學者學會使用前一種“繁瑣”的執行方式,因為它有利於你更深入地了解 C++ 程式的執行過程。