1. ホーム
  2. c++

[解決済み】C++の定義をヘッダーファイルに配置するのは良い習慣ですか?

2022-04-03 04:44:51

質問

私のC++の個人的なスタイルは、常にクラス宣言をインクルードファイルに、そして定義を .cpp ファイルで規定されているのと同じように に対するロキさんの回答 C++のヘッダーファイル、コードの分離 . 確かに、私がこのスタイルを好む理由のひとつは、Modula-2やAdaのコーディングに費やした年月に関係しているのかもしれません。

私よりずっとC++に詳しい同僚がいるのですが、彼はすべてのC++の宣言は、可能な限り、ヘッダーファイルの中にその定義を含めるべきだと主張しています。彼は、これが有効な代替スタイルであるとか、少しはましなスタイルであるとか言っているのではなく、これが現在誰もがC++で使っている新しい普遍的に認められたスタイルである、と言っているのです。

私は以前ほど体が丈夫ではないので、彼のバンドワゴンにもう少し多くの人が乗るのを見るまでは、このバンドワゴンに乗っていくことにあまり不安を感じないのです。では、このイディオムは実際どのくらい一般的なのでしょうか?

答えの構成を考えるために。それは今 ザ・ウェイ 非常に一般的か、ある程度一般的か、一般的でないか、バグアウトクレイジーか?

解決方法は?

あなたの同僚は間違っています。一般的な方法は、コードを.cppファイル(または好きな拡張子)に置き、宣言をヘッダーに置くことです。

ヘッダーにコードを入れることには、コンパイラがより巧妙にインライン化できるようになるというメリットがあります。しかし、同時に、すべてのコードがコンパイラによってインクルードされるたびに処理されなければならないので、コンパイル時間を破壊する可能性があります。

最後に、すべてのコードがヘッダーである場合、循環するオブジェクトの関係(時には望ましい)を持つことは、しばしば迷惑です。

結論から言うと、あなたは正しく、彼は間違っています。

EDITです。 ご質問の件、考えてみました。そこには テンプレートです。boostなどの新しい"modern"ライブラリの多くはテンプレートを多用し、しばしば"header only."となっています。しかし、これはテンプレートを扱うときにのみ行うべきことです。

EDITです。 ヘッダのみのコードを書くことのデメリットについて、もう少し明確にしておきたいと思う人もいるでしょう。

検索してみると、boostを扱う際にコンパイル時間を短縮する方法を探している人が結構いるようです。例えば Boost Asioでコンパイル時間を短縮する方法 1Kのファイルをboost込みでコンパイルすると、14秒かかることがわかりました。14秒は爆発的な時間ではないかもしれませんが、一般的な時間よりはるかに長く、大規模なプロジェクトを扱う場合はすぐに累積してしまいます。ヘッダのみのライブラリはコンパイル時間にかなり大きな影響を与えます。ブーストはとても便利なので、私たちはそれを許容しているだけです。

また、ヘッダだけではできないこともたくさんあります(boostでもスレッドやファイルシステムなど、部分的にリンクする必要があるライブラリがあります)。例えば、ヘッダのみのライブラリでは、単純なグローバルオブジェクトを持つことができません(シングルトンという忌まわしい方法を取らない限り)。 注意 C++17のインライン変数によって、将来的にはこの特殊な例も可能になるでしょう。

最後のポイントとして、boostをヘッダのみのコードの例として使用する場合、しばしば大きなディテールが見落とされることがあります。

Boostはライブラリであり、ユーザーレベルのコードではないので、そう頻繁に変更されることはありません。ユーザーコードの場合、すべてをヘッダーに記述してしまうと、ちょっとした変更のたびにプロジェクト全体を再コンパイルしなければならなくなります。これはとんでもない時間の無駄です(コンパイルごとに変更しないライブラリの場合はその限りではありません)。ヘッダーとソースの間で物事を分割し、さらに前方宣言を使用してインクルードを減らすと、1日に渡って合計すると、再コンパイルにかかる時間を節約できます。