C++の前置き宣言


時間:2014.03.01
場所:基地
—————————————————————————————
一、定義
前置き宣言とは、クラス、関数、またはテンプレートを宣言することであり、宣言のみであり、関連する具体的な定義は含まれません.多くの場合、include文の代わりに前置声明を使用することができます.また、通常のクラスでは、includeではなく前置宣言を使用することを推奨します.
—————————————————————————————
二、#include問題
ある物事の存在は必然的に別の物事の存在がもたらした問題を解決するためである.#includeを使用すると、#includeはコンパイラが多くのファイルを開き、関連するコンテンツを処理し、ヘッダファイルが変更されると、複数回再コンパイルされます.すなわち、includeは強い依存性を有し、前置き宣言はこの依存性を解決し、プログラムのパフォーマンスを向上させるためである.たとえば、次のような古典的なループ依存性の問題があります.
class MyClassA{MyClassB B:}
class MyClassB{MyClassa A:}

以上の2つのクラスは互いに依存しており、ループ依存を生成するには、1つのクラスを使用する前にクラスを定義する必要があるため、コンパイルは通過しません.前置声明の役割は、コンパイラがクラス名であることを知っていることをコンパイラに伝えるだけなので、上記の場合、前置があっても許可されません.彼はクラスを使用しているからです.includeはこの問題を解決できるが,ここではループ依存を生じる.
注意:完全なクラスが指定されていない場合は、クラスのオブジェクトを定義することはできません.また、インラインメンバー関数でクラスのオブジェクトを使用することはできません.たとえば、次のコードがあります.
class MyClassA;//    
class MyClassB{
public:
       void Method(){x->DoSomething();}//    ,                  
private:
       MyClassA *x;  //    ,               
};
class MyClassA{
public:
        void DoSomething(){};
private:
        MyClassA *x;
};

では、この問題を解決する方法は何ですか.2つの方法があります.1つは、2つのクラスの定義順序を変更することです.これは明らかに最も一般的です.2つ目は、Methodメソッドを非インライン関数に変更することです.これにより、クラスでxオブジェクトのメンバー関数は使用されません.
class MyClassA;//    
class MyClassB{
public:
       void Method(){}//     
private:
       MyClassA *x;  //    ,       ,   MyClassA    ,      ,     MyClassA     
};
class MyClassA{
public:
        void DoSomething(){};
private:
        MyClassA *x;
};
void MyClassB::method(){x->DoSomething();}//  ,    MyClassA       ,   ,             

Primerの本でこう言いました
class Screen;

このような前置き宣言がある場合、その宣言の後、定義する前にクラスScreenは不完全なタイプであり、コンパイラはそれに遭遇し、クラスであることしか知らず、具体的にどのメンバーが含まれているか分からない.不完全なタイプは、そのタイプのオブジェクトを定義するために使用できません.このタイプのポインタ/参照(参照自体はポインタに基づいて実装されます)のみを定義します.もちろん、定義ではなく宣言(定義)に使用して、このタイプをパラメータまたは戻りタイプの関数として使用することもできます.
—————————————————————————————
三、まとめ
クラスの事前宣言は、コンパイラにタイプを教えるだけですが、タイプのサイズ、メンバーなどの具体的な内容は伝えられません.頭の文書は一つ一つ告げられているので、彼らの使い方の違いが形成されています.前置き宣言を使用するメリットは、クラスのサイズを大幅に削減できることです.有名人の言葉:Never#include a header when a forward declaration will suffice.では、どのような状況が前に宣言できるのか、どのような状況がincludeでなければならないのか、総じて言えば、クラスのサイズやメンバーを知る必要がある場合、その定義を知る必要があります.このように、前に宣言する方法ではありません.例えば、継承することはできません.タイプには、前に宣言を使用して問題を解決することはできません.例えば、ポインタ、参照形式はincludeの代わりに前置宣言で完全に使用できます.