71

インクルード ディレクティブを正しく使用する方法C++ #include セマンティクスの質問を確認しましたが、これには対処しません。また、タイトルを入力したときに SO によって提案された他の質問にも対処しません...

もしあれば、書くことの利点は何ですか:

#include "../include/someheader.h"
#include "../otherdir/another.h"

単純なファイル名を使用する場合と比較して:

#include "someheader.h"
#include "another.h"

または、おそらく「 」のない相対名..:

#include "include/someheader.h"
#include "otherdir/another.h"

私が見る問題は次のとおりです。

  • どのソース ファイルにヘッダーが含まれているかを気にせずにヘッダーを移動することはできません。
  • 依存関係とエラー レポートのヘッダーのパスが非常に長くなる可能性があります。今日は「../dir1/include/../../include/../dir2/../include/header.h」と 1 つありました。

私が見ることができる唯一のメリットは、ファイルを移動する必要はありませんが、ヘッダーを見つけるために常に ' ' ディレクティブを使用しなくても済む可能性があることですが-I、柔軟性が失われ、sub-sub でコンパイルする複雑さがあります。 -ディレクトリなどは利点を上回っているようです。

それで、私は利益を見落としていますか?


入力していただきありがとうございます。私が見落としている「..」を使用した表記には大きな利点はないというのがコンセンサスだと思います。一般的に言えば、私は「somewhere/header.h」表記が好きです。私は新しいプロジェクトでそれを使用します。私が取り組んでいるものは決して新しいものではありません。

問題の 1 つは、さまざまなヘッダーのセットがあり、多くの場合、、、、などの接頭辞が付いているrspqr.hことです。これらはすべてディレクトリ内のコードに関連していますが、一部のヘッダーは中央のインクルード ディレクトリにあり、その他は中央のインクルード ディレクトリにあります。このディレクトリには、そのようなサブディレクトリはありません。(そして、コードの他のさまざまな領域について繰り返します。複数の場所にヘッダーがあり、他のコードによってランダムに必要とされます。)コードは長年にわたって非常に複雑になっているため、ものの移動は大きな問題です。また、makefile は、提供されるオプションに一貫性がありません。全体として、これは何十年にもわたる、それほど穏やかではないネグレクトの悲しい話です。何も壊さずにすべてを修正するのは、長くて退屈な仕事です。rsabc.hrsdef.hrsxyz.hrsmprsmprsmp-I

4

8 に答える 8

48

ヘッダーファイルがどの名前空間またはモジュールに属しているかが非常に明確になるため、パス構文を好みます。

#include "Physics/Solver.h"

すべてのモジュールがヘッダー ファイルの前に名前を付ける必要がなく、非常に自己記述的です。

ただし、「..」構文を使用することはほとんどありません。代わりに、プロジェクト インクルードで正しいベース ロケーションを指定します。

于 2009-02-28T01:42:23.753 に答える
28

の問題#include "../include/header.h"は、それが偶然に機能することが多く、その後、一見無関係に見える変更により、後で機能しなくなることです。

たとえば、次のソースレイアウトについて考えてみます。

./include/header.h
./lib/library.c
./lib/feature/feature.c

そして、インクルードパスが。でコンパイラを実行しているとしましょう-I. -I./lib。何が起こるのですか?

  • ./lib/library.cできる#include "../include/header.h"、それは理にかなっています。
  • ./lib/feature/feature.c#include "../include/header.h"それは意味がありませんが、することもできます。これは、コンパイラが#include現在のファイルの場所に関連してディレクティブを試行し、それが失敗した場合は、パス内の#include-Iエントリに関連してディレクティブを試行するためです。#include

-I./libさらに、後でパスから削除すると、#include中断し./lib/feature/feature.cます。

次のようなものが望ましいと思います。

./projectname/include/header.h
./projectname/lib/library.c
./projectname/lib/feature/feature.c

、以外のインクルードパスエントリは追加せず-I.、両方library.cを追加して、feature.cを使用します#include "projectname/include/header.h"。「プロジェクト名」が一意である可能性が高いと仮定すると、ほとんどの状況で名前の衝突やあいまいさが発生することはありません。どうしても必要な場合は、インクルードパスやmakeのVPATH機能を使用して、プロジェクトの物理レイアウトを複数のディレクトリに分割することもできます(たとえば、プラットフォーム固有の自動生成コードに対応するため。これは、使用すると実際に機能しなくなります#include "../../somefile.h")。

于 2009-02-28T03:17:37.503 に答える
9

IANALLですが、実際のCまたはC ++ソースファイルに'を入れるべきではないと思います..。これは移植性がなく、標準ではサポートされていないためです。これは、Windowsでのを使用するのと似て\います。コンパイラが他の方法で動作できない場合にのみ実行してください。

于 2009-02-28T03:02:51.470 に答える
2

ソース ツリーをネストされた名前空間と考えてください。インクルード パスにより、ディレクトリをこの名前空間のルートにプルできます。問題は、コードがディスク上でどのように構成されているかに関係なく、コード ベースの論理名前空間を形成することです。

次のようなパスは避けます。

  • "include/foo/bar.h"— 「インクルード」は非論理的で冗長なようです
  • "../foo/bar.h"—「..」は相対的な位置を想定しており、壊れやすい
  • "bar.h"— bar.h が現在のディレクトリにない限り、これはグローバル名前空間を汚染し、あいまいさを求めています。

個人的には、プロジェクトの include path — に次のようなパスを追加する傾向があります"..;../..;../../..;../../../.."

これにより、一種の非表示ルールを に適用でき、#include他のコードを壊すことなく自由にヘッダーを移動できます。もちろん、完全修飾されていない名前はあいまいになる可能性があるため (または時間の経過とともに曖昧になる可能性があるため)、注意しないと、間違ったヘッダー ファイルにバインドされるリスクが生じるという犠牲を払っています。

私はパブリック ヘッダーで s を完全に修飾する傾向がある#includeため、私のコードを使用するサード パーティは"..;../..;../../..;../../../.."プロジェクトに を追加する必要がありません。これは、私のプライベート コードとビルド システムにとって便利なだけです。

于 2009-02-28T02:42:34.030 に答える
1

その後、ファイルをプロジェクトのルートに相対的に配置し、それをソース管理にチェックインし、別の開発者がローカル システムの別の場所にチェックアウトしても、問題は解決しません。

于 2009-02-28T01:41:25.660 に答える
0

絶対 (または「拡張相対」) の別の引数を投げると、次のようなパスが含ま#include "./lib/subdir/~/subsubsubsubdir/header.h"ます。私の現在のプロジェクトでは、これらのオプションで使用される文字数は約 40k であり、コマンド ラインの制限によりエラーが発生します。"-I./~"

通常、私はそのスタイルのインクルード パスが明らかに柔軟性に欠けることを嫌いますが、この種の問題を回避するのに役立ちます。たとえば、静的ライブラリはその API を介して提供でき、"#include "lib_api.h"他のすべての組織はその場所に関連しており、ユーザーには見えない可能性があります。

于 2020-05-19T21:10:56.157 に答える