私は最近、.hファイルにたくさんの関数定義を持つライブラリを作成していましたが、ライブラリがより相互依存するようになったので、関数エラーの複数の定義にうまくいくようになったので、リファクタリングを減らすために、インラインでの私の関数ですが、私は同じ.hファイルで定義されたクラスのために何も変更する必要がないのだろうかと思います。クラスも重複してはならないのですか?複数の定義エラーが発生することなく、.hファイルにクラスと関数を入れないのはなぜですか?
答えて
ヘッダーに変数、関数、クラスを宣言し、そのヘッダーを複数の翻訳単位に組み込むことができます。問題はありません。しかし、あなたがやっているのは、という定義のの機能です。
クラスは、あなたがそうでなければ、あなたのクラスは非常に有用ではないので、は限り各コピーの内容が正確に一致するよう —この特別なルールが重要であり、複数の翻訳単位でそれらを定義することという点で特殊です。 がと宣言されているクラスは、すぐに使用することはできませんが、宣言されている関数はすぐに使用できます。
これは、2種類の種類の異なる性質の単なる結果です。
// Declarations
extern int x; // variable
void foo(); // function
class T; // class
// Definitions
int x; // variable
void foo() {} // function
class T {}; // class
あなたは、宣言されたクラスだけをあまり使うことができない理由を詳しく述べることができますか? – zimzam
@zimzam:宣言されているクラス(私たちはこれを「前方宣言」と呼んでいます)は、非常に限られた方法でしか使用できません。基本的にクラスの「サイズ」を知る必要がないもの、またはそのメンバーがその中にいるもの。だからクラス 'T'では' T * 'や' T& 'を使って何かを行うことができます(あるいはそれをテンプレートのパラメータとして使うこともできます)。 'T'をインスタンス化したい、あるいは値を返す関数を宣言することを含む値による返り値をコピーするか、そのメンバーのいずれかにアクセスしたい場合は、完全な定義が必要です。関数呼び出しでこれが当てはまることはありません –
これは読んだので意味がありますが、クラスの定義が同一であることを確認するのが簡単ならば、関数定義で同じことをするのはなぜですか?両方の関数定義が同じ場合、コンパイル時エラーを報告するのはなぜですか?代わりに2つの同一の関数定義が警告を出すのは理にかなっていませんか? – zimzam
ファンクションは、.h
ファイルにも入れることができますが、ファンクション定義だけでも使用できます。宣言ではなく、がテンプレート関数である場合を除きます。基本的にクラスと同じルールですが、クラスでは、クイック・アンド・ダーティなやり方でクラス内にすべてを入れ、定義と宣言を組み合わせます。これは本当に良い習慣ではありません。
ので:
これは.hファイルに行く:
int DoSomething(double x, double y);
そして、これは、.cppファイル
int DoSomething(double x, double y)
{
return static_cast<int>(x+y);
}
に行きながら、この(あなたがテンプレートを心配している場合、そうでありませんこれを無視してください)、のみ .hファイルに移動します。
template <typename T>
int DoSomething(T x, T y)
{
return static_cast<int>(x+y);
}
このすべてのことは楽しいものではありません。それには非常に正当な理由があります。なぜなら、.h
ファイルはAPIを表し、.cpp
ファイルはの実装を表します。理想的には、APIは、事前に計画しており変更することはありません。一方、バグを修正するために、実装を更新することができます。
cppファイルをダイナミックリンクライブラリ(dll)または共有ライブラリにコンパイルすることができます。このライブラリは、APIを変更せずに更新できます。したがって、あなたのプログラムでは、同じAPIを.h
ファイルに含めて、をと別の実装にリンクすることができます。
質問:テンプレートがファイル.h
にのみ含まれる理由は、コンパイル済みのものは事前定義されたタイプである必要があるからです。どのような型であるのか知らなくても、何かをコンパイルすることはできません。
話はページに行くことができます...しかし、これは基本(私が願って)を説明するのに十分だと思います。
私はこのレベルの説明のためにテンプレートを全く言及しませんでしたが、あなたがそうしたいのであれば、これは "これは.hファイルにしか行かない"というのは価値がないかもしれません。これは、通常、関数テンプレート_useful_を作成する唯一の方法です。 –
@LightnessRacesinOrbitそれを有用にするとどういう意味ですか?どうしたらうまくいくのでしょうか?説明してください。 –
'.cpp'ファイルに関数テンプレートを定義できます。しかし、別の翻訳単位で得られたスペシャライゼーションを使用したい場合、あなたは固執しています。そのため、私たちは通常、プログラム全体でテンプレートを使用できるようにするために、あるいは少なくとも複数の場所でテンプレートを使用できるようにするため、ヘッダー(またはヘッダーに含まれるファイル)に入れていました。 –
- 1. アーカイブとリンクするときに「複数定義」エラーが発生するのはなぜですか?
- 2. cppファイル全体でクラスを定義するとリンカーエラーが発生しないのはなぜですか?
- 3. min関数に複雑な引数を入れるとエラーになるのですか?なぜ?(EclipseのC++)
- 4. なぜこのコードを関数に入れないと、NULLポインタ例外が発生しますか?
- 5. なぜangularjsに関数エラーが発生していないのですか?
- 6. インスタンスを定義するときにあいまいなエラーが発生するのはなぜですか?
- 7. なぜgdbの関数に入ることができないのですか?
- 8. __eq__の引数型を定義するとMyPy型のエラーが発生するのはなぜですか?
- 9. なぜヘッダーファイルで宣言し、ファイルで定義すると多重定義エラーが発生するのですか?
- 10. なぜsetVisibility()関数に定義がないのですか?
- 11. なぜ関数定義に型がないのですか?
- 12. Python 3 - この変数がこの関数で定義されていないのはなぜですか?
- 13. 関数からグローバル変数にアクセスしようとすると、未定義の変数エラーが発生するのはなぜですか?
- 14. これらのJavaScript関数はなぜ未定義ですか?
- 15. クラス定義全体を ".h"に入れると、実行可能ファイルが大きくなりますか?
- 16. 致命的なエラー:定義されていない関数 - なぜですか?
- 17. この変数に未定義のエラーが発生するのはなぜですか?
- 18. 複数の.hと.mファイル、複数のインターフェイス定義
- 19. C++関数プロトタイプが.hファイルのクラス定義で宣言されていますが、.cppで定義されていない関数
- 20. 構文Pythonで複数の関数を定義しようとするとエラーが発生しますか?
- 21. なぜこの「関数は定義されていません」というエラーが表示されますか?
- 22. ここでメモリリークが発生するのはなぜですか?メイン関数で
- 23. なぜエラー - 未定義の関数defstruct
- 24. JavaScript関数 "a"が定義されていないのはなぜですか?
- 25. 関数名が定義されていないのはなぜですか?
- 26. コールバック関数が定義されていないのはなぜですか?
- 27. これらの未定義の変数がJavaScriptと等しくないのはなぜですか?
- 28. 変数が定義されていないとエラーが発生しないようにしますか?
- 29. C++のpoll()関数でエラーが発生するのはなぜですか?
- 30. 共有パッケージにクラス直列化の定義を入れないと、なぜClassNotFoundExceptionが生成されますか?
クラス*定義*を作成していないため、クラス*宣言*を作成しています。 – EJP
'.hファイルにたくさんの関数定義を持つライブラリを書いていました。それが問題です。ヘッダーは*定義*ではなく*宣言*を含んでいなければなりません。 'リファクタリングを減らすために、私はすべての関数をインラインで宣言しました。それはそれを"修正する "正しい方法ではありません。ヘッダーに関数*宣言*を残し、実装*をcppファイルに移動します。 – dxiv
ありがとう@EJP、私はクラス内で定義された関数は、デフォルトでインラインとして定義されているので、なぜそれらを変更する必要がないのかを説明していると思います。 – zimzam