分離式編譯模式

分離編譯模式源於C語言,在C++語言中繼續沿用。簡單地說,分離編譯模式是指:一個程式(項目)由若干個源檔案共同實現,而每個源檔案單獨編譯生成目標檔案,最後將所有目標檔案連線起來形成單一的執行檔的過程。

基本介紹

  • 中文名:分離編譯模式
  • 外文名:Separate Compilation Pattern
  • 學科領域:計算機
  • 所屬分類:編程術語
模式定義,模式由來,模式要點,

模式定義

一個程式(項目)由若干個源檔案共同實現,而每個源檔案單獨編譯生成目標檔案,最後將所有目標檔案連線起來形成單一的執行檔的過程。

模式由來

分離編譯模式是C/C++組織原始碼和生成執行檔的方式。在實際開發大型項目的時候,不可能把所有的源程式都放在一個頭檔案中,而是分別由不同的程式設計師開發不同的模組,再將這些模組匯總成為最終的可執行程式。
這裡就涉及到不同的模組(源檔案)定義的函式和變數之間的相互調用問題。C/C++語言所採用的方法是:只要給出函式原型(或外部變數聲明),就可以在本源檔案中使用該函式(或變數)。每個源檔案都是獨立的編譯單元,在當前源檔案中使用但未在此定義的變數或者函式,就假設在其他的源檔案中定義好了。每個源檔案生成獨立的目標檔案(obj檔案),然後通過連線(Linking)將目標檔案組成最終的執行檔。
程式編譯的簡要過程包括預處理(Preprocessing)、編譯(Compilation)、彙編(Assembly)和連線(Linking)。

模式要點

理解分離編譯模式要注意以下幾點。
(1)每個函式或外部變數(全局變數)只能被定義一次,但可以被多次“聲明”。見下面的程式
#include <iostream>
using namespace std;
void func();
void func();
void func(){
         cout<<”This ia a demo”<<endl;
}
int main(){
         func();
}
函式func()被多次聲明,並不影響程式的正常編譯和運行。其實這正是C++分離編譯模式的特點之一。在一個源檔案中允許同時包含定義和聲明同一個標識符的語句,這樣就有利於頭檔案內容的組織。
(2)函式聲明也是有作用域的。
類的成員函式只能在類體中聲明。對於外部函式,如果是在一個函式體內聲明另一個外部函式,那么該函式聲明的作用域就是從聲名處開始到函式體結束為止。在別的位置要調用這個函式,還必須再次聲明。
如下面的程式,由兩個源檔案組成,a.cpp和b.cpp。函式func()定義在a.cpp中,b.cpp中有兩個函式show()和main()都調用了a.cpp中定義的函式func()。如果堅持將函式聲明放在函式體內部,則在函式show()和main()中必須分別對函式func()進行聲明,否則編譯出錯。程式如下:
/***a.cpp***/
#include <iostream>
Using namespace std;
void func(){
         cout<<”This is a demo”<<endl;
}
/***end of a.cpp***/
 
/****b.cpp****/
void show(){
void func(); //func()的聲明必不可少
    func();
}
int mian(){
         void func(); // func()的聲明必不可少
         func();
         show();
}
/****end of b.cpp****/
通常情況下,將外部函式或外部變數的聲明放在.h頭檔案中。對於不在源檔案中定義的函式(或變數),只要將相應的頭檔案通過#include指令包含進來,就可以正常使用了。
(3)一個函式被聲明卻從未定義,只要沒有發生函式調用,編譯連線是不會出錯的。
參考如下程式。
#include <iostream>
using namespace std;
class Demo{
public:
         void func1();
         void func2();
};
void Demo::func1(){
         cout<<”This is a demo”<<endl;
}
int main(){
         Demo obj;
obj.func1();
}              
觀察以上程式可以,類Demo的定義是不完整的,因為成員函式func2未完成定義,但是func2從未發生過調用,所以,函式只有生命沒有定義在不發生函式調用的情況下是可以通過編譯連線的。
從分離編譯模式的角度來看,函式Demo::func2()有可能是在別的源檔案中定義的。下面的程式就說明了這一點。
/****a.cpp****/    
#include <iostream>
using namespace std;
class Demo{
public:
     void func1();
     void func2();
};
void Demo::func2(){
     cout<<”This is func2”<<endl;
}       
/****end of a.cpp****/ 
 
/****b.cpp****/    
#include <iostream>
using namespace std;
class Demo{
public:
     void func1();
     void func2();
};
void Demo::func1(){
     cout<<”This is func1”<<endl;
}
int main(){
    Demo obj;
    obj.func2();
}
/****end of b.cpp****/ 
觀察以上程式,類Demo有兩個成員函式,它們分別在a.cpp和b.cpp源檔案中實現。類Demo是被“分離“實現的。所以,分離編譯模式關心的是函式的調用規範(函式原型),至於函式是否真正實現要到連線的時候才能被發現。
由分離編譯模式也可以得到頭檔案的書寫規範。頭檔案的目的是提供其他源檔案中定義的,可以被當前源檔案使用的內容(函式、變數等)的聲明。因此,有個基本的假設是:頭檔案要被多次被不同的源檔案包含。因此,一般都不在頭檔案中定義函式、定義外部變數,因為這樣的頭檔案只能被包含一次,沒有被包含第二次的可能性,背離了設立頭檔案的初衷。
在一個源檔案中定義函式,在另一個源檔案中調用該函式,是分離編譯模式下十分普遍的現象。但是如果定義的不是一個普通函式,而是一個函式模板,卻可能發生錯誤。

相關詞條

熱門詞條

聯絡我們