C++Primer学習ノート_92_大規模なプログラムに使用されるツール-ネーミングスペース[続き1]

5982 ワード

大型プログラム用のツール
--ネーミングスペース[続き1]
二、ネストネーミングスペース
ネストされたネーミングスペースは、ネストされた役割ドメインです.その役割ドメインは、そのネーミングスペースを含む内部にネストされます.ネストされたネーミングスペースの名前は、通常のルールに従います.周辺ネーミングスペースで宣言された名前は、ネストされたネーミングスペースの同じ名前の宣言によってブロックされます.ネストされたネーミングスペースの内部で定義された名前は、そのネーミングスペースにローカルです.周辺ネーミングスペース以外のコードは、ネストされたネーミングスペースの名前を限定名で参照することしかできません.
ネストされたネーミングスペースは、ライブラリ内のコードの組織を改善します.
namespace cplusplus_primer
{
namespace QueryLib
{
class Query
{
    //...
};

Query operator&(const Query &,const Query &);
}

namespace Bookstore
{
class Item_base
{
    //...
};

class Bulk_item : public Item_base
{
    //...
};
}
}

ライブラリプロバイダが、ライブラリ内の各セクションの名前がライブラリ内の他のセクションの名前と競合することを防止する必要がある場合、ネストされたネーミングスペースは便利です.
ネストされたネーミングスペースのメンバーの名前は、周辺ネーミングスペースの名前とネストされたネーミングスペースの名前で構成されます.
    cplusplus_primer::QueryLib::Query q;
//P604   17.17
namespace cplusplus_primer
{
namespace simpleSI
{
//...1
}

namespace handleSI
{
//...2
}
}

三、名前のないネーミングスペース
ネーミングスペースはネーミングされていないものでもよく、ネーミングされていないネーミングスペースは定義時に名前が指定されていません.名前の付いていないネーミングスペースは、キーワードnamespaceで始まり、キーワードnamespaceの後に続くカッコで区切られた宣言ブロックです.
ネーミングされていないネーミングスペースは、他のネーミングスペースとは異なり、ネーミングされていないネーミングスペースの定義は、指定されたファイル内で不連続で特定のファイルに局所的に存在し、複数のテキストファイルを越えないことができます.各ファイルには、名前のないネーミングスペースがあります.
名前のないネーミングスペースは、ファイルにローカルなエンティティを宣言するために使用されます.名前のないネーミングスペースで定義された変数は、プログラムの開始時に作成され、プログラムが終了するまで存在します.
ネーミングされていないネーミングスペースで定義された名前は直接使用できます.結局、ネーミングスペースの名前は定義されていません.役割ドメインオペレータを使用して、名前のないネーミングスペースのメンバーを参照することはできません.
ネーミングされていないネーミングスペースで定義された名前は、ネーミングスペースを含むファイルにのみ表示されます.別のファイルに名前のないネーミングスペースが含まれている場合、2つのネーミングスペースは関連しません.2つのネーミングスペースでは、同じ名前を定義できますが、これらの定義は異なるエンティティを参照します.
名前空間で定義されていない名前は、名前空間が定義されている役割ドメインで見つけることができます.ファイルの最外層の役割ドメインで名前が付けられていない名前空間を定義する場合は、名前が付けられていない空間の名前は、グローバル役割ドメインで定義されている名前とは異なる必要があります.
int i;
namespace
{
    int i;
}

i = 10; //Error:ambiguous

他の任意のネーミングスペースと同様に、ネーミングされていないネーミングスペースも別のネーミングスペースの内部にネストできます.ネーミングされていないネーミングスペースがネストされている場合、名前は通常の方法で周辺ネーミングスペース名を使用してアクセスします.
namespace local
{
namespace
{
int i;
}
}

    local::i = 10;	//OK

【地雷に注意】
ヘッダファイルが名前のないネーミングスペースを定義している場合、ヘッダファイルを含む各ファイルで、ネーミングスペースの名前は異なるローカルエンティティを定義します.
他のすべての方法では、名前のないネーミングスペースのメンバーは通常のプログラムエンティティです.
【ファイル内の静的宣言の代わりに名前の付いていないネーミングスペース】
標準C++にネーミングスペースを導入する前に、プログラムは名前をstaticとして宣言し、ファイルにローカルにする必要があります.ファイル内の静的宣言の使用はC言語から継承され、C言語ではstaticと宣言されたローカルエンティティは、宣言されたファイルの外に表示されません.
C++はファイル静的宣言に賛成しない.不賛成の特徴は、将来のバージョンではサポートされない可能性がある特徴です.[ファイルにローカルなエンティティを宣言するために使用される]の代わりに、ファイルが静的であることを避ける必要があります.
//P605   17.19
namespace cplusplus_primer
{
namespace Matrix_primer
{
class matrix
{
    //...
};
matrix operator*(const matrix &,const matrix &);
}
}

cplusplus_primer::Matrix_primer::matrix
cplusplus_primer::Matrix_primer::operator*(const matrix &,const matrix &);

四、ネーミングスペースメンバーの使用
【ベストプラクティス】
関数または他の役割ドメインの内部に加えて、ヘッダファイルにはusing指示またはusing宣言が含まれるべきではありません.トップレベルの役割ドメインにusingインジケータまたはusing宣言のヘッダファイルが含まれており、ヘッダファイルを含むファイルに名前を注入する効果があります.ヘッダファイルは、インタフェースの一部である名前のみを定義し、実装で使用する名前は定義しないでください.
1、using声明、要約再述
using std::map;
using std::pair;
using std::size_t;
using std::string;
using std::vector;

1つのusing宣言は、プログラムで使用される名前にかかわらず、1つのネーミングスペースメンバーのみを一度に導入することで、非常に明確になります.
2、using宣言の役割ドメイン
USing宣言ポイントから、using宣言を含む役割ドメインの末尾まで名前が表示されます.外部の役割ドメインで定義された同名エンティティはブロックされます.
簡潔な名前は、宣言された役割ドメインとネストされた役割ドメインでのみ使用できます.役割ドメインが終了すると、完全な限定名を使用する必要があります.
using宣言は、グローバル役割ドメイン、ローカル役割ドメイン、またはネーミングスペース役割ドメインに表示されます.クラス役割ドメインのusing宣言は、定義されたクラスのベースクラスで定義された名前に限定されます.
3、ネーミングスペース別名
使用可能なネーミングスペース別名は、短い同義語をネーミングスペース名に関連付けます.たとえば
namespace cplusplus_primer
{
    //...
}

短い同義語に関連付けることができます.
namespace primer = cplusplus_primer;

元のネーミングスペース名が定義されていない場合は、エラーが発生します.
ネーミングスペースエイリアスは、ネストされたネーミングスペースを参照することもできます.
namespace Qlib = cplusplus_primer::QueryLib;
Qlib::Query tq;

1つのネーミングスペースには多くの別名があり、すべての別名と元のネーミングスペースを互換的に使用できます.
4、using指示
usingは、表示される名前を制御できません.すべて表示されます.
usingは、特定のネーミングスペースのすべての名前を表示するように指示し、制限はありません.短いフォーマット名は、usingインジケータが表示される役割ドメインの末尾までusingインジケータポイントから使用できます.
【地雷に注意】
プログラミングをusingで指示してみてもいいですが、複数のライブラリを使用すると、名前の競合のすべての問題が再導入されます.
5、using指示と役割ドメイン
using宣言は、名前が名前空間メンバーのローカル別名であるように、using宣言が表示される役割ドメインに直接挿入されます.このような声明は局所化されているため、衝突の機会は最も小さい.
usingは、ネーミングスペースのメンバー名を宣言しない別名を示します.逆に、ネーミングスペースのメンバーをネーミングスペース自体とusingの指示を含む最近の役割ドメインに昇格させる効果があります.
次の例を示します.fでは、Aの名前がグローバル役割ドメインのfの定義の前に表示されるようにします.
namespace A
{
int i,j;
}

void f()
{
    using namespace A;
    cout << i * j << endl;
}

【ベストプラクティス】
usingは、ネーミングスペース自体の実装ファイルで使用される場合に役立つことを示します.
6、using指示例
namespace blip
{
    int bi = 16,bj = 15,bk = 23;
}
int bj = 0;

void manip()
{
    using namespace blip;

    ++ bi;  //17
    ++ bj;  //Error:ambiguous

    ++ ::bj;    //1
    ++ blip::bj; //16

    int bk = 97;
    ++ bk;  //98
}

manipのusingプロンプトにより、manipはblipのすべての名前に直接アクセスできます.これらのメンバーの名前を参照できる簡略化された形式を使用します.
【警告:using指示の使用を避ける】
usingは、1つのネーミングスペースからのすべての名前を注入することを示しています.その使用は信頼できません.1つの文だけで、ネーミングスペースのすべてのメンバー名が突然表示されます.この方法は簡単そうに見えるが、それ自体の問題もある.アプリケーションが多くのライブラリを使用し、usingでこれらのライブラリの名前を表示するように指示すると、グローバルネーミングスペース汚染の問題が再発生します.
また、ライブラリの新しいバージョンにインポートすると、作業中のプログラムのコンパイルに失敗する可能性があります.新しいバージョンでアプリケーションが使用している名前と競合する名前が導入されると、この問題が発生します.
もう1つの問題は、using指示による二義的なエラーは使用場所でしか検出できないことであり、この後の検出は、特定のライブラリが導入されてから競合が発生する可能性があり、プログラムがライブラリの新しい部分を使用し始めると、以前に検出されなかった競合が発生する可能性があることを意味する.USing指示に依存するよりも、プログラムで使用される各ネーミングスペースの名前に対してusing宣言を使用すると、ネーミングスペースに注入される名前の数を減らすことができ、using宣言による二義的なエラーは、点検出ではなく宣言点で発生するため、発見と修正が容易になります.