30

一部の古いコードをリファクタリングしているときに、実際には静的であるはずのいくつかのパブリック メソッドを削除しました。これらは、a) メンバー データを操作したり、他のメンバー関数を呼び出したりしないためです。b) 他の場所で役立つ可能性があるためです。

これにより、「ヘルパー」関数をグループ化する最善の方法について考えるようになりました。Java/C# の方法は、プライベート コンストラクターで静的関数のクラスを使用することです。

class Helper  
{  
private:  
  Helper() { }
public:  
  static int HelperFunc1();  
  static int HelperFunc2();  
};

ただし、C++ であるため、名前空間を使用することもできます。

namespace Helper  
{  
  int HelperFunc1();  
  int HelperFunc2();  
}

ほとんどの場合、名前空間アプローチを好むと思いますが、各アプローチの長所と短所を知りたいと思いました。たとえば、クラス アプローチを使用した場合、オーバーヘッドは発生しますか?

4

7 に答える 7

38

オーバーヘッドは問題ではありませんが、名前空間にはいくつかの利点があります

  • コンパイルの依存関係を低く抑えながら、物事をより論理的にグループ化して、別のヘッダーで名前空間を再度開くことができます
  • 名前空間エイリアシングを有利に使用できます(デバッグ/リリース、プラットフォーム固有のヘルパーなど)。

    たとえば、私は次のようなことをしました

    namespace LittleEndianHelper {
       void Function();
    }
    namespace BigEndianHelper {
       void Function();
    }
    
    #if powerpc
       namespace Helper = BigEndianHelper;
    #elif intel
       namespace Helper = LittleEndianHelper;
    #endif
    
于 2008-09-17T06:57:30.913 に答える
11

を使用class(またはstruct)する可能性namespaceがあるのは、タイプが必要な場合です。たとえば、次のようになります。

struct C {
  static int f() { return 33; }
};

namespace N {
  int f() { return 9; }
}

template<typename T>
int foo() {
  return T::f();
}

int main() {
  int ret = foo<C>();
//ret += foo<N>(); // compile error: N is a namespace
  return ret;
}
于 2008-09-18T00:40:24.930 に答える
6

Pieter の優れた応答に加えて、名前空間のもう 1 つの利点は、別の場所の名前空間、特に構造体に配置したものを前方宣言できることです...

//Header a.h
// Lots of big header files, spreading throughout your code
class foo
{
  struct bar {/* ... */);
};

//header b.h
#include a.h // Required, no way around it, pulls in big headers
class b
{
  //...
  DoSomething(foo::bar);
};

そして名前空間で...

//Header a.h
// Big header files
namespace foo
{
  struct bar {/* ... */);
}

//header b.h
// Avoid include, instead forward declare 
//  (can put forward declares in a _fwd.h file)
namespace foo
{
  struct bar;
}

class b
{
  //...
  // note that foo:bar must be passed by reference or pointer
  void DoSomething(const foo::bar & o);
};

何百ものソース ファイルにまたがるプロジェクトになってしまうと、ヘッダーを少し変更すると、前方宣言がコンパイル時間に大きな違いをもたらします。

パーセバルから編集

列挙型エラーのために答えが良すぎて死ぬことはありませんでした(コメントを参照)。列挙型 (現在の C++ ではなく、C++0x でのみ前方宣言できる) を構造体に置き換えました。

于 2008-09-17T07:30:11.477 に答える
4

名前空間を使用する主な利点は、名前空間を再度開いて後で追加できることです。クラスではそれを行うことはできません。これにより、このアプローチは疎結合ヘルパーに対してより適切になります (たとえば、すべての STL が ::std にあるように、ライブラリ全体にヘルパー名前空間を設定できます)。

クラスの主な利点は、クラスを使用してクラス内にネストできることです。クラスに名前空間をネストすることはできません。これにより、このアプローチは密結合ヘルパーにとってより適切になります。

それらをクラスと名前空間に持つことによる余分なオーバーヘッドはありません。

于 2008-09-17T06:55:00.780 に答える
3

Namespaces offer the additional advantage of Koenig lookup. Using helper classes may make your code more verbose - you usually need to include the helper class name in the call.

Another benefit to namespaces is in readability later on. With classes, you need to include words like "Helper" to remind you later that the particular class isn't used to create objects

In practice, there's no overhead in either. After compilation, only the name mangling used differs.

于 2008-09-17T09:05:24.787 に答える
3

C++ で名前空間を適切に使用するにはどうすればよいですか?からの私の回答の一部をコピー/トリミング/作り直し ました。.

「使う」を使う

"using" を使用して、ヘルパー関数の "プレフィックス" を繰り返さないようにすることができます。例えば:

struct AAA
{
   void makeSomething() ;
} ;

namespace BBB
{
   void makeSomethingElse() ;
}

void willCompile()
{
   AAA::makeSomething() ;
   BBB::makeSomethingElse() ;
}

void willCompileAgain()
{
   using BBB ;

   makeSomethingElse() ; // This will call BBB::makeSomethingElse()
}

void WONT_COMPILE()
{
   using AAA ; // ERROR : Won't compile

   makeSomething() ; // ERROR : Won't compile
}

名前空間の構成

名前空間はパッケージ以上のものです。別の例は、Bjarne Stroustrup の「The C++ Programming Language」にあります。

「特別版」の8.2.8 Namespace Compositionで、AAA と BBB の 2 つの名前空間を CCC と呼ばれる別の名前空間にマージする方法について説明しています。したがって、CCC は AAA と BBB の両方のエイリアスになります。

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

独自のカスタム名前空間インターフェイスを構築するために、さまざまな名前空間から選択したシンボルをインポートすることもできます。私はまだこれの実用的な使い方を見つけていませんが、理論的にはクールです。

于 2008-12-20T14:30:07.397 に答える
3

ヘルパー関数を作成するときは、匿名の名前空間を使用する傾向があります。それらは(通常)それらを気にするモジュールによってのみ見られるべきであるため、依存関係を制御するための良い方法です。

于 2008-09-18T13:27:24.587 に答える