16

ときどき、自分のコード スタイルについての考え方に異議を唱える、私が維持しているコードに出くわします。今日はその中の1日でした...

スコープ演算子を使用してグローバルスコープを定義する理由については承知しています。実際、ここでは、スコープのないスコープ解決演算子は、その理由を説明する素晴らしいリンクです。

しかし、今日は考えさせられるものを見ました。問題のクラスはすべてプロジェクトの名前空間にラップされていましたが (良いことです!)、グローバル スコープ演算子が大量に使用されていることがわかりました。つまり、Cライブラリのすべてに使用されていました(uint8_tなどを除く...はい、プログラマーはこのライブラリの.hバージョンを使用しました。実行していたg ++のバージョンが新しいC ++に関する警告をまだスローしていたようです)標準)。これは役に立ちますか?私はこれを単なる文字の無駄だと考えています (this ポインターを使用することを思い出します... コピー コンストラクターと代入演算子の場合を除き、どのオブジェクトがどれであるかを明確にするのに役立ちます)。何か不足していますか?確かに、誰かがやって来て、usleep() や stderr (「::」の使用が最も多い箇所) の行に沿って名前を付けることができますが、そうはなりません。そうすることで何かがひどく壊れる可能性があることを彼らは知っていますか?どの時点で、スコープ演算子に関して「ねじ込み」と言い、自分の名前空間内で特定の方法で関数に名前を付けている誰かが問題を求めていると自分に言い聞かせますか?

だから私の質問は...このコンテキストでグローバルスコープ演算子を使用する「正しい」(私が理解している主観的な)方法は何ですか? std または独自の名前空間に含まれていないものはすべて、グローバル スコープを明示的に定義する必要がありますか? 私は注意を怠り、「std::」を使用して using ディレクティブを回避する傾向がありますが、ここでグローバル スコープ演算子を使用することで得られるものはありますか? 明確にするために、現在の名前空間から問題の変数または関数を取得していないという事実に役立つと考える傾向がありますが、それを含めるか、今日の開発を与えないかで迷っています。

いつものように、コードをよりクリーンに、より読みやすく、そして (もちろん) 大幅に素晴らしいものにするために、ヘルプとガイダンスに感謝します。

4

4 に答える 4

3

ほぼ完全にスタイルに関連しているため、これに対する正しい答えはほとんどありませんが、宣言/定義をインポートする場所から変更したい場合は例外ですそれらを使用し、スコープを指定せず、usingディレクティブ (名前空間からサブセットをインポートする) またはusing namespaceディレクティブを使用してそれらをインポートし、名前空間からセット全体をインポートします。

ほとんどのusingディレクティブは便利なディレクティブとして使用されますが、どの宣言/定義が使用されているかを指示する強力な方法です。私の好みは、スコープを指定せずに宣言をインポートすることです。これを行うと、視覚的なノイズを減らしながら、必要に応じて簡単に変更できます。また、スコープを指定すると、宣言を取得している場所から「ロックイン」されることになります (それを変更するには、グローバル検索と置換を実行する必要があります)。

競合が発生した場合 (複数の名前空間からインポートされた同じ名前の宣言された項目を使用しようとした場合) は、コンパイラが通知するので、実際の危険はありません。

于 2013-06-25T06:04:09.233 に答える
1

以下のケースを考慮してください。

公共図書館。

公開ヘッダーを使用してエクスポート可能なライブラリを作成しています。また、ヘッダーがどの環境に含まれるかはまったくわかりません。たとえば、誰かが次のことを行う可能性があります。

namespace std = my_space::std;
#include "your_header"

また、単純に :std::list<int>などを使用すると、すべての定義が破損します。そのため、::すべてのグローバルの先頭に追加することをお勧めします。これにより、何を使用しているかを完全に確認できます。もちろん、using(C++11 で) またはtypedef- を行うこともできますが、ヘッダーに入れるのは間違った方法です。


共同 .cc/.cpp ファイル。

公開されていない独自のコードの内部では、自分だけでなく編集も可能です。名前空間の外部から何を使用するかを発表することをお勧めします。たとえば、プロジェクトでstd::vector. 次に、適切な場所にusingディレクティブを配置します。

// some includes

using vector = ::std::vector<int>;  // C++11
typedef ::std::vector<int> vector;  // C++03

namespace my_namespace {
...
}  // namespace my_namespace

すべてのインクルードの後、または特定の関数内に置くことができます。コードを制御するだけでなく、コードを読みやすくし、式を短くします。

もう 1 つの一般的なケースは、グローバル C 関数と C++ コードの混合です。typedef関数名で s を実行することはお勧めできません。この状況では、C 関数の先頭にグローバル スコープ解決演算子を追加する必要があります。これは::、誰かが同じ名前空間で同じシグネチャを持つ関数を実装した場合のコンパイルの問題を回避するためです。

相対型と名前空間には使用しないでください::。そうしないと、名前空間を使用する利点がまったく失われます。


独自のコード。

やりたいことをやりたいようにやる。良い方法は 1 つだけです。それは、独自のコードを快適に使用する方法です。本当に、あいまいさを解決する必要がない場合は、この状況でグローバル スコープの解決を気にしないでください。

于 2013-11-17T15:03:48.520 に答える