名前のない名前空間がstaticよりも優れているか?


129

名前のない名前空間はstaticキーワードよりも優れていますか?


ただし、標準化委員会によると、名前のない名前空間はnamespace-staticの十分な代替品ではありません。名前のない名前空間が失敗し、機能するだけのインスタンスがまだいくつかありますstatic
legends2k 2013

回答:


133

基本的には、C ++ 03標準のセクション7.3.1.1/2を参照しています。

名前空間スコープでオブジェクトを宣言する場合、staticキーワードの使用は非推奨です。名前のない名前空間は、優れた代替手段を提供します。

この段落はC ++ 11ですでに削除されていることに注意してください。static関数は標準ごとに廃止されなくなりました!

それでも、主にキーワードstatic変数の宣言と関数にのみ適用され、ユーザー定義の型には適用されないため、無名の名前空間はstaticキーワードよりも優れています

次のコードはC ++で有効です

   //legal code
   static int sample_function() { /* function body */ }
   static int sample_variable;

しかし、このコードは無効です:

   //illegal code
   static class sample_class { /* class body */ };
   static struct sample_struct { /* struct body */ };

したがって、解決策は、名前のない名前空間です。これは、

   //legal code
   namespace 
   {  
        class sample_class { /* class body */ };
        struct sample_struct { /* struct body */ };
   }

なぜunnamed-namespaceがに勝るのか説明してほしいstatic

また、(標準に従って)名前空間スコープでオブジェクトを宣言する場合、staticキーワードの使用は推奨されないことに注意してください。


11
より一般的には、名前のない名前空間は外部リンクを許可します。これが、local-to-translation-unitクラス宣言を可能にするものです。また、たとえば、外部リンケージ文字列定数をテンプレート引数として使用できます。
乾杯とhth。-Alf

10
別の回答でFred Nurkが述べたように、このdeprecated発言は最新のC ++ 0x FCD(n3225)から削除されたようです。
Matthieu M.

36
あなたはあなた自身の質問に答え、自分に感謝を言っています:-o
manpreet sing h

11
cppでクラスを定義するだけの場合との違いは何ですか(匿名の名前空間なし、静的なし)?
Luchian Grigore 2013年

6
@LuchianGrigoreケース2のリンクの問題は.cpp、同じ名前のクラスを定義しています。
Xaqq 2014

8

これに関連する興味深い問題があります:

この関数はモジュールによって内部的に使用され、モジュールの外部からはアクセスできないようになっているため、staticキーワードまたは無名namespaceを使用して、モジュール(翻訳単位)の一部の関数を作成するとします。(名前namespaceのないsには、関数の他に、データと型の定義も内部的に作成できるという利点があります)。

時間の経過とともに、モジュールの実装のソースファイルが大きくなり、それをいくつかの個別のソースファイルに分割すると、コードの整理が容易になり、定義をすばやく見つけて、独立してコンパイルできるようになります。

しかし、ここで問題に直面します。これらの関数は、実際にはモジュールを参照してstaticいるのでstaticはなく、ソースファイル(翻訳単位)を参照しているため、モジュールを参照することはできません。そのモジュールの他の部分(オブジェクトファイル)からアクセスできるようにするために、それらを非作成にする必要があります。しかし、これはまた、モジュールに対して非表示/プライベートではなくなったことも意味します。外部リンケージがあるため、他のモジュールからアクセスできますが、これは本来の意図ではありませんでしたstatic

名前namespaceもこの問題を解決しません。特定のソースファイル(翻訳単位)に対しても定義されており、外部からアクセスできないためです。

一部のnamespaceprivate、つまり、その中で定義されているものはすべて、それが属するモジュールによって内部的に使用されることを意図していると指定できればすばらしいでしょう。しかし、もちろんC ++には「モジュール」のような概念はなく、ソースファイルに密接にバインドされている「翻訳単位」だけがあります。


3
それはとにかくハックで限定的な解決策ですが、内部の静的関数または名前空間付きの関数を含むcppファイルを「メイン」cppファイルに含めることができます。次に、これらの「サテライト」cppファイルをビルドから除外すれば完了です。2つ以上の「メイン」cppファイルがあり、どちらも「衛星」cppファイルの1つからそのクールな機能を使用したい場合の唯一の問題...
Sergey

静的関数でプライベート/保護/パブリックで継承を使用することは解決策ではありませんか?
Ali

C ++ 20には、問題を解決するモジュールが導入されています。
LF

4

C ++標準は、セクション7.3.1.1名前なし名前空間の段落2を読みます。

名前空間スコープでオブジェクトを宣言する場合、staticキーワードの使用は非推奨です。unnamed-namespaceは、より優れた代替手段を提供します。

staticは、オブジェクト、関数、および無名共用体の名前にのみ適用され、型宣言には適用されません。


5
いいえ、ありません。ドラフトはしました。そして、そのすぐ後の別の草案がこのばかげた変更を元に戻しました。
underscore_d
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.