Frage

Beim Refactoring von altem Code habe ich eine Reihe öffentlicher Methoden entfernt, die eigentlich statische Methoden sein sollten, da sie a) keine Mitgliedsdaten bearbeiten oder andere Mitgliedsfunktionen aufrufen und b) weil sie sich an anderer Stelle als nützlich erweisen könnten.

Dies veranlasste mich, darüber nachzudenken, wie man „Hilfsfunktionen“ am besten gruppieren kann.Der Java/C#-Weg wäre die Verwendung einer Klasse statischer Funktionen mit einem privaten Konstruktor, z. B.:

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

Da Sie jedoch C++ sind, können Sie auch einen Namespace verwenden:

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

In den meisten Fällen würde ich wahrscheinlich den Namespace-Ansatz bevorzugen, aber ich wollte wissen, welche Vor- und Nachteile jeder Ansatz hat.Würde beispielsweise bei Verwendung des Klassenansatzes ein Mehraufwand entstehen?

War es hilfreich?

Lösung

Overhead ist kein Problem, Namespaces haben einige Vorteile, obwohl

  • Sie können einen Namespace in einem anderen Header wieder öffnen, Dinge Gruppierung mehr logisch, während kompilieren halten Abhängigkeiten niedrig
  • Sie können Namespace-Aliasing zu Ihrem Vorteil nutzen (Debug / Release, plattformspezifische Helfer, ....)

    z. Ich habe Sachen gemacht wie

    namespace LittleEndianHelper {
       void Function();
    }
    namespace BigEndianHelper {
       void Function();
    }
    
    #if powerpc
       namespace Helper = BigEndianHelper;
    #elif intel
       namespace Helper = LittleEndianHelper;
    #endif
    

Andere Tipps

Ein Fall, in dem eine class (oder struct) über namespace verwenden könnte, ist, wenn man eine Art, zum Beispiel benötigt:

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;
}

zu Pieters ausgezeichneter Antwort hinzuzufügen, ein weiterer Vorteil von Namensräumen ist, dass Sie Sachen erklären weiterleiten können, die Sie in einem Namespace setzen woanders, vor allem structs ...

//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);
};

Und mit Namespaces ...

//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);
};

Weiterleiten deklariert einen großen Unterschied zu Ihrem Kompilierungszeiten nach kleinen Header Änderungen vornehmen, wenn Sie mit einem Projekt am Ende hunderte von Quelldateien überspannt.

Bearbeiten von paercebal

Die Antwort war zu gut es wegen eines ENUM-Fehler sterben zu lassen (siehe Kommentar). I ersetzt Aufzählungen (die voraus erklärt werden kann nur in C ++ 0x, nicht in der heutigen C ++) von structs.

Der Hauptvorteil eines Namespace ist, dass Sie es wieder öffnen können und später weitere Sachen hinzufügen, können Sie nicht, dass mit einer Klasse tun. Dies macht dieser Ansatz besser für lose gekoppelte Helfer (zB Sie einen Helfer-Namespace für Ihre gesamte Bibliothek haben könnte, ähnlich wie alle STL ist in :: std)

Der Hauptvorteil einer Klasse ist, dass man es Nest innerhalb der Klasse es verwenden, kann nicht verschachtelt ein Namespace in einer Klasse. Dies macht diesen Ansatz besser für eng gekoppelte Helfer.

Sie werden keinen zusätzlichen Aufwand haben sie in einer Klasse gegen einen Namespace mit.

Namensräume bieten den zusätzlichen Vorteil von Koenig-Lookup. Mit Hilfsklassen können Ihren Code ausführlicher machen - Sie müssen in der Regel die Helferklassennamen im Aufruf enthalten

.

Ein weiterer Vorteil ist Namespaces später in der Lesbarkeit. Mit Klassen, müssen Sie Wörter wie „Helper“ enthalten, die Sie später daran zu erinnern, dass die besondere Klasse keine Objekte verwendet wird, erstellen

In der Praxis gibt es keinen Overhead in entweder. Nach der Kompilierung nur Mangeln der Name verwendet wird, unterscheidet.

Einen Teil meiner Antwort von kopiert/gekürzt/überarbeitet Wie verwendet man Namespaces in C++ richtig?.

Verwendung von „using“

Sie können „using“ verwenden, um zu vermeiden, dass das „Präfix“ Ihrer Hilfsfunktion wiederholt wird.Zum Beispiel:

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
}

Zusammensetzung des Namensraums

Namespaces sind mehr als Pakete.Ein weiteres Beispiel findet sich in Bjarne Stroustrups „The C++ Programming Language“.

In der „Special Edition“, bei 8.2.8 Namensraumzusammensetzung, beschreibt er, wie man zwei Namensräume AAA und BBB zu einem anderen Namensraum namens CCC zusammenführen kann.Somit wird CCC zu einem Alias ​​sowohl für AAA als auch für BBB:

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

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

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

Sie können sogar ausgewählte Symbole aus verschiedenen Namespaces importieren, um Ihre eigene benutzerdefinierte Namespace-Schnittstelle zu erstellen.Ich habe noch keinen praktischen Nutzen dafür gefunden, aber theoretisch ist es cool.

Ich neige dazu, anonyme Namespaces zu verwenden, wenn Hilfsfunktionen zu schaffen. Da sie sollten (in der Regel) nur durch das Modul zu sehen, die sich um sie kümmert, es ist ein guter Weg, um Abhängigkeiten zu steuern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top