2011-01-21 7 views
24

こんにちは、読んでいただきありがとうございます。私はクラスの.h ファイルまたは実装ファイル.CPPにクラスコンストラクタの本体を定義することができヘッダファイルVS実装(.cpp)ファイルにコンストラクタを定義する

これはちょうど、とにかくここで行く「個人の好み」のカテゴリに該当する可能性があります ...。これらの2つのスタイルは、コンパイラが特定のプロジェクト(私のプロジェクトはdllを意味します)内で関係する限り、おそらく同じです。 同じことは実際にどのメンバー関数にも当てはまります。ヘッダーファイルで定義するか、そこで宣言してからcppファイルで定義することができます。

しかし...

は、私は別のプロジェクトで、このようなクラスのヘッダーファイル(複数可)を含める必要がある場合には(最終的には、ヘッダファイルを使用するコードが異なるDLLで終わることを意味する)ことがわかりましたヘッダーファイルに実際の実装があると、コンパイル時に頭痛が発生します(リンクしていない...私はその点に到達していません)。 なぜですか?まあ、私はあまり詳しくは触れませんが、コンパイラは他のヘッダファイルなどで定義されている可能性があるすべての関数を解決しようとしています...貧しい開発者がさまざまなヘッダファイルを取得するよう強制します...

LONGSTORY short:

ヘッダーファイルを実装から解放し、 '宣言'のためだけに使用することは常に最善の方法ではありませんか?それは、余分な迷惑メールをたくさん持ち歩かずに、複数のプロジェクトにそれらを含めるほうが簡単になります。

これについてご意見はありますか? ありがとう!

答えて

21

実装をインライン化する必要がある場合(例:簡単なゲッター/セッター)には、ヘッダーを実装から解放してください。もちろん、それらがテンプレートでない限り。

コンストラクタの例外を作成する理由はありません。それらを.cppファイルに入れます。

+1

実装をヘッダに入れることができる場合もあります。もし、2つの異なるファイルが両方ともお互いを必要とするならば、それはヘッダーで行うことはできません、それはcppで行われなければなりません。 –

+0

「できません」を意味します。「できません」。そうでなければ、良い点。 – Thomas

+2

「簡単な」例外は、簡単なコンストラクタにも簡単に適用できます。違った扱いをする理由もないし、インライン化させない理由もない。 –

17

注目すべき重要なポイントは、メンバー関数がヘッダーファイル内で定義されている場合、クラス本体内にあるか、または明示的にinlineとしてマークする必要があります。それがどんな機能がなければならないことは明白だが、コンパイラは、各コンパイル単位で定義が含まれるようになりますので

class A { 
    public: 
    A(); 
}; 

A::A() { 
    // constructor body 
} 

それは間違っている理由は次のとおりです。言い換えれば、ヘッダーファイルでこれを行うには平野間違っています一度だけ定義されます。コンストラクタは、インラインである、両方のケースで

class A { 
    public: 
    inline A() { // inline isn't required here, but it's a good style 
    // constructor body 
    } 
}; 

class A { 
    public: 
    inline A(); 
}; 

inline A::A() { 
    // constructor body 
} 

または:ここで同じことを行うための正しい方法があります。これを通常の行外関数にする唯一の正しい方法は、ヘッダーではなく実装ファイルで定義することです。これは、これらの2つのアプローチの最も重要な違いです。

ここで、インライン化は最適化であることに注意してください。そして、いつものように最適化は、必要があることが証明されるまで避けてください。インライン化されていない関数の本体を変更した場合、定義されているユニットを再コンパイルするだけで、誰もがすぐに新しい実装の使用を開始するという互換性の問題があります。インライン関数では、関連ヘッダを含むすべてのユニットを再コンパイルする必要があります。これは、特にヘッダーが異なるプロジェクト間で異なる人によって使用されている場合に痛みを伴う可能性があります。

つまり、できるだけ特定の関数呼び出しがパフォーマンスのボトルネックであることがプロファイリングされるまで、定期的な行外定義を使用してください。このルールの唯一の合理的な例外は、些細なセッターとゲッターですが、それらを使用しても慎重であるほうが良いでしょう。ある日、彼らは些細なことになるかもしれません。

1

注意事項:ヘッダーファイルを変更するには、そのヘッダーファイルを含むすべてのファイルを再構築する必要があります。ほとんどのビルドシステムは、変更されたヘッダーファイルに依存するソース(* .cpp/.cc)ファイルを再構築します。

ヘッダーファイルで定義されたクラスのメソッドを変更すると、ヘッダーファイルを含むすべてのソースファイルが再構築されます。ソースファイル内のメソッドを変更すると、ソースファイルのみが再構築されます。これは、中規模から大規模のプロジェクトでは問題になる可能性があります。

ビルドプロセスを簡素化するために、クラスのほとんどのメソッドは、ソースファイルで定義する必要があります。インライン展開のための小さなメソッドや他の候補をヘッダファイルに定義する必要があります。

関連する問題