すべてのc ++コースで、すべての教師は常にusing namespace std;
ファイルの#include
sの直後に.h
を配置します。これは、そのヘッダーを別のプログラムに含めることで、名前空間をプログラムにインポートするため、おそらく気づかず、意図せず、または欲しくないため、危険であると思われます(ヘッダーの包含は非常に深くネストできます)。
だから私の質問は二重です:using namespace
をヘッダーファイルで使用すべきではないこと、および/またはそれを元に戻す何らかの方法がありますか?
//header.h
using namespace std {
.
.
.
}
同じ行に沿ってもう1つ質問:ヘッダーファイル#include
に対応する.cpp
ファイルに必要なすべてのヘッダー、ヘッダー定義に必要なヘッダーのみ、.cpp
ファイルを#include
、残りはなし、またはextern
として必要なすべてを宣言する必要があります?
質問の背後にある理由は上記と同じです。.h
ファイルを含めるとき、私は驚きを望みません。
また、私が正しい場合、これはよくある間違いですか?実世界のプログラミングと、そこにある「本物の」プロジェクトを意味します。
ありがとうございました。
ヘッダーでusing namespace
を使用することは絶対にしないでください。ヘッダーを含む他のファイルのコードの意味が予期せず変更される可能性があるためです。 using namespace
を元に戻す方法はありません。これは非常に危険なもう1つの理由です。通常、grep
などを使用して、using namespace
がヘッダーで呼び出されないようにし、より複雑なことをしようとはしません。おそらく静的コードチェッカーもこれにフラグを立てます。
ヘッダーには、コンパイルする必要があるヘッダーのみを含める必要があります。これを強制する簡単な方法は、各ソースファイルのヘッダーを常に他のヘッダーの前に最初に含めることです。ヘッダーが自己完結型でない場合、ソースファイルはコンパイルに失敗します。たとえば、ライブラリ内の実装詳細クラスを参照する場合、#include
の代わりに前方宣言を使用できます。これは、このような前方宣言クラスの定義を完全に制御できるためです。
私はそれを一般的なものと呼ぶかどうかはわかりませんが、たまに否定的な結果を知らない新しいプログラマーによって書かれたものであることが時々明らかになります。通常、リスクを修正するのは比較的簡単なので、リスクについての少しの教育で問題を処理します。
Sutter and Alexandrescuの項目59 「C++コーディング標準:101ルール、ガイドライン、およびベストプラクティス」 :
59。ヘッダーファイルまたは#includeの前に名前空間を使用して記述しないでください。
名前空間
using
sは便宜のためであり、他の人に与えるものではありません。#include
ディレクティブの前にusing
宣言またはusing
ディレクティブを記述しないでください。結果:ヘッダーファイルには、名前空間レベルの
using
ディレクティブまたはusing
宣言を記述しないでください。代わりに、すべての名前を明示的に名前空間修飾します。
ヘッダーファイルは、1つ以上のソースファイルのゲストです。 using
ディレクティブと宣言を含むヘッダーファイルには、乱暴な仲間も含まれています。
using
declarationは、1人のバディをもたらします。 using
directiveは、名前空間内のすべてのバディを取り込みます。教師によるusing namespace std;
の使用はusingディレクティブです。
さらに深刻なのは、名前の衝突を避けるための名前空間です。ヘッダーファイルは、インターフェイスを提供することを目的としています。ほとんどのヘッダーは、現在または将来、どのコードがそれらを含む可能性があるかを認識しません。内部の利便性のためにヘッダーにusing
ステートメントを追加すると、そのヘッダーの潜在的なすべてのクライアントに便利な名前が付けられます。それは名前の衝突につながる可能性があります。そして、それは単なる失礼です。
ヘッダーの内部にヘッダーを含めるときは注意する必要があります。大規模なプロジェクトでは、非常に複雑な依存関係チェーンを作成し、実際に必要なよりも大きい/長い再構築をトリガーできます。 この記事 と フォローアップ をチェックして、C++プロジェクトでの優れた物理構造の重要性について詳しく学んでください。
絶対に必要な場合(クラスの完全な定義が必要な場合)にのみヘッダー内にヘッダーを含め、どこでも(クラスが必要な場合はポインターまたは参照)前方宣言を使用する必要があります。
名前空間については、ヘッダーファイルで明示的な名前空間スコープを使用する傾向があり、cppファイルにはusing namespace
のみを配置します。
Goddard Space Flight Centerのコーディング標準(CおよびC++用)を調べてください。それは、以前よりも少し難しいことがわかりました-SOの質問に対する更新された回答を参照してください。
GSFC C++コーディング標準には次のように書かれています。
§3.3.7各ヘッダーファイルは、ユーザーに
#include
必要なファイルを強制するのではなく、#include
コンパイルする必要があるファイルを使用します。#includes
は、ヘッダーに必要なものに制限されます。他の#includes
はソースファイルに配置する必要があります。
相互参照された最初の質問には、GSFC Cコーディング標準からの引用とその根拠が含まれていますが、実質は同じです。
ヘッダーのusing namespace
は危険です。元に戻す方法がわかりません。検出は簡単ですが、ヘッダーファイルでusing namespace
を検索するだけです。その最後の理由で、実際のプロジェクトでは一般的ではありません。経験豊富な同僚は、誰かがそのようなことをするとすぐに文句を言うでしょう。
実際のプロジェクトでは、インクルードするファイルの量を最小限に抑えようとします。インクルードするファイルが少ないほど、コンパイルが速くなります。それは皆の時間を節約します。ただし、ヘッダーファイルが何かを前に含める必要があると想定する場合は、ヘッダーファイル自体を含める必要があります。それ以外の場合、ヘッダーは自己完結型ではありません。
「[using
宣言]を元に戻す方法はありますか?」
using
宣言はスコープの影響を受けることを指摘しておくと便利だと思います。
#include <vector>
{ // begin a new scope with {
using namespace std;
vector myVector; // std::vector is used
} // end the scope with }
vector myOtherVector; // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified
事実上はい。 using
宣言のスコープを制限することにより、その効果はそのスコープ内でのみ持続します。そのスコープが終了すると「元に戻されます」。
using
宣言が他のスコープ外のファイルで宣言されると、ファイルスコープを持ち、そのファイル内のすべてに影響します。
ヘッダーファイルの場合、using
宣言がファイルスコープにある場合、これはヘッダーが含まれるファイルのスコープに拡張されます。
プログラミングのすべてのものと同様に、プラグマティズムは独断主義、IMOに勝つはずです。
プロジェクト全体で決定を下す限り(「私たちのプロジェクトはSTLを広範囲に使用しており、すべてにstd ::。を追加する必要はありません」)、問題は見当たりません。リスクを抱えているのは名前の衝突だけです。結局のところ、STLが広く普及しているため、問題になることはほとんどありません。
一方、1つの(非プライベート)ヘッダーファイルで1人の開発者が決定した場合、チーム間で混乱が発生するため、回避する必要があります。
あなたが正しいです。また、ファイルには、そのファイルに必要なヘッダーのみを含める必要があります。 「現実世界のプロジェクトでよくあることを間違えていますか?」 -ああ、そうだ!
次のようにネストされた名前空間で宣言を書くと、C++ヘッダーで「使用」を安全に使用できると思います。
namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED
{
/*using statements*/
namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED
{
/*declarations*/
}
}
using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED;
これには、名前空間を使用せずに、 'DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED'で宣言されたもののみを含める必要があります。 mingw64コンパイラでテストしました。