2009-11-27 13 views
28

ヘッダーファイルでのみクラスを宣言して実装することの違いは、ヘッダーのprotypeクラス効果的な.cppファイルを実装します。.hファイル内または.cppファイル内でのクラスの実装の違い

// File class.h 
class MyClass 
{ 
private: 
    //attributes 
    public: 
    void method1(...); 
    void method2(...); 
    ... 
}; 

//file class.cpp 
#include "class.h" 

void MyClass::method1(...) 
{ 
    //implementation 
} 

void MyClass::method2(...) 
{ 
    //implementation 
} 

ばかりのヘッダアプローチ:

// File class.h 
class MyClass 
{ 
private: 
    //attributes 
public: 
    void method1(...) 
    { 
     //implementation 
    } 

    void method2(...) 
    { 
    //implementation 
    } 

    ... 
}; 

私が主な違いを得ることができ、私は通常のアプローチの違いを意味について話しているものをよりよく説明すること

: 2番目のケースでは、コードは同じ実装のインスタンスをさらに生成する必要がある他のすべてのファイルに含まれているため、暗黙の冗長性があります。最初のケースではコードはそれ自身でコンパイルされ、MyClassのオブジェクトに参照されるすべてのコールはclass.cppの実装にリンクされます。

他の違いはありますか?状況に応じて別のアプローチではなくアプローチを使用するほうが便利でしょうか?また、メソッドの本体をヘッダファイルに直接定義することは、そのメソッドをインライン化するためのコンパイラへの暗黙の要求です。

+0

適切なプリプロセッサガードをお持ちの場合、同じインプリメンテーションのインスタンスがそれ以上作成されません。 –

+0

あなたは#ifndef _CLASS_H_ #define _CLASS_H_などについて話していますか? – Jack

+9

@Andrew:確かに、それは2つになります。cppファイルには同じヘッダーが含まれており、プリプロセッサのガードに関係なく内容が完全にコンパイルされ、コンパイルされたコンテンツは出力オブジェクトファイルに存在します。重複はリンカーによってのみ削除されます。プリプロセッサガードは、翻訳ユニット間で共有するのではなく、単一の翻訳ユニットでヘッダーの二重包含を正常に処理する必要があります。 –

答えて

33

実際の主な違いは、メンバ関数定義がヘッダーの本文にある場合、もちろんそのヘッダーを含む各変換単位ごとにコンパイルされることです。プロジェクトに数百または数千のソースファイルが含まれていて、問題のクラスがかなり広く使用されている場合、これは多くの繰り返しを意味します。たとえ各クラスが2つまたは3つの他のクラスによってのみ使用されていても、ヘッダーにコードが多くなればなるほど、より多くの作業ができます。

メンバ関数定義が独自の変換単位(.cppファイル)内にある場合、それらは一度コンパイルされ、関数宣言のみが複数回コンパイルされます。

クラス定義で定義された(単に宣言されていない)メンバ関数は、暗黙的にinlineです。しかしinlineは、人々がそれが合理的に推測できるものを意味するものではありません。 inlineは、関数の複数の定義が異なる翻訳単位で表示され、後で一緒にリンクされることは合法だと言います。これは、異なるソースファイルが使用されるヘッダーファイルにクラスが含まれている場合に必要です。そのため、言語は役立ちます。

inlineは、関数が便利にインライン化される可能性があることをコンパイラに示すヒントですが、名前にもかかわらず、オプションです。コンパイラーが洗練されているほど、インライン化について独自の判断を下すことができ、ヒントの必要性が少なくなります。実際のインラインタグよりも重要な点は、関数がコンパイラでまったく利用可能かどうかである。関数が別の変換単位で定義されている場合は、その呼び出しがコンパイルされたときに関数を使用できないため、呼び出しがインライン化する場合は、コンパイラではなくリンカーでなければなりません。

あなたはそれを行うための第3の可能な方法を考慮して、より良いの違いを見ることができるかもしれない:

// File class.h 
class MyClass 
{ 
    private: 
     //attributes 
    public: 
     void method1(...); 
     void method2(...); 
     ... 
}; 

inline void MyClass::method1(...) 
{ 
    //implementation 
} 

inline void MyClass::method2(...) 
{ 
    //implementation 
} 

は今、暗黙のインラインが邪魔であることを、この「すべてのヘッダの間にいくつかの違いが残っています"アプローチ、および"ヘッダーとソース "のアプローチです。翻訳単位間でコードをどのように分割するかは、翻訳単位がどのようになるかに影響します。

+0

infact私は "コンパイラへのリクエスト"について話していましたが、それはオプションの効果的なインライン展開です。 – Jack

+0

はい、私はC++の新しい読者が忘れてしまった最初の3つの段落。 –

7

実装を含むヘッダーを変更すると、そのヘッダーを含む他のすべてのクラスが強制的に再コンパイルおよび再リンクされます。

ヘッダーは実装よりも頻繁に変更されないため、実装を別のファイルに入れておくと、かなりのコンパイル時間を節約できます。

他の回答が既に指摘されているように、はい、ファイルのclassブロック内にメソッドを定義すると、コンパイラはインライン化します。

1

はい、クラス定義内でメソッドを定義することは、それらを宣言することと同等です。inline他に違いはありません。ヘッダーファイルにすべてを定義することにメリットはありません。

ほとんどのコンパイラがexportをサポートしていないという事実のため、テンプレートメンバの定義もヘッダファイルに含めなければならないので、通常はC++ではテンプレートクラスで見えます。しかし、普通のテンプレートでないクラスでは、あなたのメソッドを実際にinlineと宣言しない限り、これを行うことに意味はありません。

+1

これはなぜ投票されましたか?それは私に十分な(と有益な)見える.... –

+3

明らかにトローリング。説明のないダウンボォートは常にトローリングしています。 – AnT

+1

これを行う明確なポイントは、それがより短いことです。欠点を考慮して、パブリックヘッダーの実際の理由ではありません。しかし、単一のモジュール内で内部的に使用される小さなユーティリティクラスの場合、それは完璧です。 –

7

はい、コンパイラは、メソッドをインライン化しようとしますが、同様にヘッダファイルに直接宣言:

class A 
{ 
public: 
    void method() 
    { 
    } 
}; 

私は、ヘッダファイルに実装を分離するには、以下の便利さと考えることができます:

  1. ます」同じコードが複数の翻訳単位に含まれているためコードが膨らんでいません
  2. コンパイル時間が大幅に短縮されます 。 ヘッダーファイルの変更の場合、 コンパイラは、直接または間接的に を含む他のすべての ファイルをビルドする必要があります。私は非常に を追加するためだけに バイナリ全体を構築するのに不満があると思います。
0

以前は、いろいろなCORBAディストリビューションの相違から遮るモジュールを作成し、さまざまなOS /コンパイラ/ CORBAの組み合わせで一貫して動作することが期待されていました。ヘッダーファイルに実装することで、簡単なインクルードでプロジェクトに追加することがより簡単になりました。同じ技術は、コードを呼び出すコードが、異なるライブラリまたは別のOSでコンパイルされているときに再コンパイルが必要なときに、同時にコードが再コンパイルされることを保証しました。だから、

私のポイントである、あなたは再利用可能で、それヘッダがメインプロジェクトや余分なファイルを追加することとは対照的に、いくつかの他のプロジェクトとの統合での利点を提供する様々なプロジェクト間に再コンパイルすることが予想され、むしろ小さなライブラリを持っている場合外部のlib/objファイルを再コンパイルする。

1

私の主な違いは、ヘッダーファイルがクラスの「インターフェイス」のようなものであり、クライアントが特定の実装について心配することなく、そのクラスのパブリックメソッド(サポートする操作)それらのつまり、cppファイルだけが変更され、コンパイル時間がずっと少なくなるため、実装の変更からクライアントをカプセル化する方法です。

関連する問題