分離コンパイルモードの概要

5276 ワード

サンプルコードコンパイル実行環境:VS 2012+Debug+Win 32.
1.コンパイルモードの定義を分離する
分離コンパイルモードはC言語に由来し、C++言語で引き続き使用されます.簡単に言えば、分離コンパイルモードとは、1つのプログラム(プロジェクト)が複数のソースファイルによって共に実現され、各ソースファイルが個別にコンパイルされてターゲットファイルが生成され、最後にすべてのターゲットファイルを接続して単一の実行可能ファイルを形成するプロセスである.
2.分離コンパイルモードの由来
分離コンパイルモードは、ソースコードをC/C++で整理し、実行可能ファイルを生成する方法です.実際に大規模なプロジェクトを開発する場合、すべてのソースプログラムを1つのヘッダファイルに置くことはできませんが、それぞれ異なるプログラマーが異なるモジュールを開発し、これらのモジュールをまとめて最終的な実行可能プログラムにします.
ここでは、異なるモジュール(ソースファイル)で定義された関数と変数間の相互呼び出しの問題について説明します.C/C++言語では、関数のプロトタイプ(または外部変数宣言)を指定すれば、この関数(または変数)をソースファイルで使用できます.各ソースファイルは独立したコンパイルユニットであり、現在のソースファイルで使用されているが、この定義されていない変数または関数は、他のソースファイルで定義されていると仮定します.各ソースファイルは独立したターゲットファイル(objファイル)を生成し、接続(Linking)によってターゲットファイルを最終的な実行可能ファイルに構成する.
プログラムコンパイルの簡単な手順には、前処理(Preprocessing)、コンパイル(Compilation)、アセンブリ(Assembly)、接続(Linking)が含まれます.
3.コンパイルモードを分離するポイント
分離コンパイルモードを理解するには、以下の点に注意してください.
(1)各関数または外部変数(グローバル変数)は1回のみ定義できますが、複数回「宣言」することができます.以下の手順を考察する.
#include <iostream>
using namespace std;
void func();
void func();
void func(){
    cout<<”This ia a demo”<<endl;
}

int main(){
    func();
}

関数func()は複数回宣言され、プログラムの正常なコンパイルと実行に影響しません.実はこれがC++分離コンパイルモードの特徴の一つです.同じ識別子を定義して宣言する文を1つのソースファイルに同時に含めることができ、ヘッダファイルの内容の組織に役立ちます.
(2)関数宣言にも役割ドメインがある.クラスのメンバー関数は、クラスでのみ宣言できます.外部関数の場合、ある関数内で別の外部関数を宣言する場合、その関数宣言の役割ドメインは、名前から関数体が終了するまでです.この関数を別の場所で呼び出すには、再度宣言する必要があります.
次のプログラムのように、a.cppとb.cppの2つのソースファイルから構成されています.関数func()定義はa.cppで、b.cppには2つの関数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の定義は不完全であり,メンバ関数func 2は定義を完了していないがfunc 2は呼び出しが発生したことがないため,関数呼び出しが発生しない場合にコンパイルによって接続できるのは生命のみである.
コンパイルモードを分離する観点から,関数Demo::func 2()は別のソースファイルで定義されている可能性がある.次の手順で説明します.
/***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***/    

/***a.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ソースファイルでそれぞれ実現される2つのメンバー関数があります.クラスDemoは「分離」によって実装されている.したがって、分離コンパイルモードは、関数の呼び出し仕様(関数プロトタイプ)に関心を持ち、関数が実際に実装されるかどうかは接続時に発見される.
分離コンパイルモードによってもヘッダファイルの書き込み仕様が得られる.ヘッダファイルの目的は、現在のソースファイルで使用されている内容(関数、変数など)によって宣言できる他のソースファイルで定義されているものを提供することです.したがって、ヘッダファイルが複数の異なるソースファイルに含まれるという基本的な仮定があります.したがって、一般的には、ヘッダファイルに関数を定義したり、外部変数を定義したりしない.このようなヘッダファイルは一度しか含まれず、二度目を含まれる可能性がなく、ヘッダファイルの設立の趣旨から逸脱しているからである.
1つのソースファイルで関数を定義し、別のソースファイルで関数を呼び出すことは、分離コンパイルモードで非常に一般的な現象です.ただし、一般的な関数ではなく、関数テンプレートを定義している場合は、エラーが発生する可能性があります.
参考文献
[1]陳剛.C++上級進級教程[M].武漢:武漢大学出版社、2008.