web-dev-qa-db-ja.com

.cppファイルでC ++名前空間メソッドを定義する正しい方法

おそらく複製ですが、検索するのは簡単ではありません...

次のようなヘッダーを指定します。

_namespace ns1
{
 class MyClass
 {
  void method();
 };
}
_

.cppファイルでは、いくつかの方法でmethod()が定義されています。

バージョン1:

_namespace ns1
{
 void MyClass::method()
 {
  ...
 }
}
_

バージョン2:

_using namespace ns1;

void MyClass::method()
{
 ...
}
_

バージョン3:

_void ns1::MyClass::method()
{
 ...
}
_

それを行うための「正しい」方法はありますか?これらのすべてが同じことを意味しないという点で、これらの「間違った」ものはありますか?

95
Mr. Boy

バージョン2は不明であり、理解するのは容易ではありません。どのネームスペースMyClassが属しているかがわからず、単に非論理的であるためです(同じネームスペースにないクラス関数?)

バージョン1は、名前空間で関数を定義していることを示しているため正しいです。

_::_スコープ解決演算子を使用して名前空間_ns1_のMyClass::method ()を参照したため、バージョン3も適切です。バージョン3が好きです。

Namespaces(C++) を参照してください。これはこれを行う最良の方法です。

44
GILGAMESH

5年後、私はこれに言及すると思いました。

using ns1::MyClass;

void MyClass::method()
{
  // ...
}
23
Puzomor Croatia

バージョン4(以下)を使用しています。これは、バージョン1(解像度の定義の簡潔さ)とバージョン3(最大限に明示的)の利点のほとんどを組み合わせているためです。主な欠点は、人々がそれに慣れていないことですが、私はそれが私が気にしない代替案より技術的に優れていると考えるので。

バージョン4:名前空間エイリアスを使用した完全修飾を使用します。

#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
    ...
}

私の世界では、すべてが明示的に修飾されているため、名前空間エイリアスを頻繁に使用しています-できない(変数名など)か、既知のカスタマイズポイント(関数テンプレートのswap()など)でない限り.

13
Dietmar Kühl

バージョン3では、クラスと名前空間の間の関連付けが非常に明示的になりますが、入力は増えます。バージョン1はこれを回避しますが、ブロックとの関連付けをキャプチャします。バージョン2はこれを隠す傾向があるので、私はそれを避けたい。

4
Paul Joireman

「コーディングスタイルの問題」だけではないことがわかりました。数2は、ヘッダーファイルでexternと宣言された変数を定義および初期化するときにリンクエラーにつながります。私の質問の例を見てください。 cppファイルの名前空間内の定数の定義

3
jakumate

Googles C++ Style Guide は、バージョン1をインデントせずに指示します。

Googles C++ Style Guide for namespaces

すべての方法は正しく、それぞれに長所と短所があります。

バージョン1では、各関数の前に名前空間を記述する必要がないという利点があります。欠点は、特に複数のレベルの名前空間がある場合、退屈なIDを取得することです。

バージョン2では、コードをよりクリーンにしますが、CPPに複数のネームスペースが実装されている場合、他のネームスペースを(そのcppファイルに対して)役に立たなくするために、他のネームスペースを他の関数や変数に直接アクセスできます。

バージョン3では、さらに入力する必要があり、関数行が画面よりも大きくなる可能性がありますが、これはデザインエフェクトには不適切です。

一部の人々がそれを使用する別の方法もあります。最初のバージョンに似ていますが、識別の問題はありません。

こんな感じです:

#define OPEN_NS1 namespace ns1 { 
#define CLOSE_NS1 }

OPEN_NS1

void MyClass::method()
{
...
}

CLOSE_NS1

それぞれの状況に適したものを選択するのはあなた次第です=]

2
Renan Greinert

Num.3(別名、冗長バージョン)を選択します。それはもっとタイピングですが、その意図はあなたとコンパイラに正確です。実際に投稿した問題は、実際の世界よりも簡単です。現実の世界では、クラスメンバだけでなく、定義の他のスコープがあります。定義はクラスだけではそれほど複雑ではありません-その名前空間やグローバルスコープなどとは異なり、そのスコープが再び開かれることはありません。

Num.1これは、クラス以外のスコープで失敗する可能性があります-再オープン可能なもの。そのため、このアプローチを使用してネームスペースで新しい関数を宣言するか、インラインをODRで置換することができます。これは、いくつかの定義(特に、テンプレートの専門化)に必要になります。

Num.2これは非常に壊れやすく、特に大規模なコードベースでは、ヘッダーと依存関係が変化するため、プログラムのコンパイルに失敗します。

Num.3これは理想的ですが、入力することはたくさんあります-定義する目的はsomethingですこれはまさにそれを行い、コンパイラーはあなたが間違いを犯していないこと、定義が宣言と同期していないことなどを確認するために働きかけます。

2
justin