2013-01-16 8 views
29

È buona norma usare lo spazio dei nomi come classe statica? Per esempio:Utilizzare uno spazio dei nomi al posto di una classe statica in C++?

namespace MyStaticFunctions { 
    void doSomething(); 
} 

Versus:

class MyStaticFunctions { 
    static void doSomething(); 
} 
+0

preferisco "extern" perché solo C++ può fare questo in OOP;) Anche per C o compatibilità con Objective C. – 9dan

+3

* "Va bene o va bene esercitarsi a usare uno spazio dei nomi come una classe statica" * - In effetti è di gran lunga una pratica migliore della seconda opzione. Quest'ultimo è solo preferito (o meglio necessario) se hai bisogno di uno "spazio dei nomi template" * o vuoi rendere un intero spazio dei nomi un amico di un'altra classe (anche se potrebbe essere discutibile). –

risposta

34

Non esiste una "classe statica" in C++, quindi da un punto di vista C++ non la si utilizza "come una classe statica", la si utilizza "come spazio dei nomi". È certamente prassi comune utilizzare gli spazi dei nomi per raggruppare le funzioni.

Spetta a te, però, quanto grande vuoi che siano i gruppi. Non è insolito che le librerie C++ utilizzino un singolo spazio dei nomi per l'intera interfaccia pubblica. Ciò potrebbe essere una sorpresa per qualcuno che è abituato a (diciamo) Java, dove le classi sono spesso utilizzate per raggruppare insieme un minor numero di metodi statici. Dato che C++ è stato qui per primo, si potrebbe dire che Java sta usando le classi come spazi dei nomi.

Quindi, in C++ non si tende a vedere classi simili a java.util.Collections o java.lang.Math, pieno di membri statici. Se vuoi gruppi di funzioni come quella in C++, usa gli spazi dei nomi.

L'eccezione (non c'è sempre un caso speciale in C++?) È tipi di tratti come std::numeric_limits<T>, in cui il parametro del modello fa fare alla classe qualcosa che un namespace non può fare. È possibile definire uno spazio dei nomi numeric_limits contenente i modelli di funzione max<T>(), min<T>() ecc., Ma non è altrettanto valido. In primo luogo, raggruppa le cose in modo leggermente diverso, il tipo T appare "in basso nella gerarchia". In secondo luogo, non fa tutto ciò che fa un tipo di carattere, perché non esiste un "modello di oggetto" che ti consente di definire un valore numeric_limits::digits<T>.

Non conosco C# abbastanza bene da commentare gli usi pratici delle classi statiche, ma AFAIK è solo una classe limitata a non avere membri non statici, quindi è analoga a quelle classi Java.

+1

+1 Un altro caso in cui una * "classe statica" * potrebbe rivelarsi utile se si desidera trasformare un intero spazio dei nomi in un amico di un'altra classe (anche se il progetto potrebbe essere discutibile in primo luogo, ma può essere molto utile a volte). –

+4

Un altro caso in cui _namespaces_ sono migliori. puoi usare 'using namespace MyStaticFunctions' se hai intenzione di usare più di questi funtction in una funzione – balki

4

Dipende.

Il metodo è correlato logicamente a una classe? In tal caso, rendilo membro, altrimenti inseriscilo in un namespace.

Funzionalmente, sono uguali, ma c'è più per il codice che per la funzione, giusto? Ad esempio, si consideri un metodo che restituisce il nome della classe:

struct MyClass 
{ 
    static std::string getName() { return "MyClass"; } 
} 

Si potrebbe, ovviamente, posizionare il metodo al di fuori, in un namespace, e ottenere lo stesso risultato, ma appartiene logicamente alla classe.

+1

Che cosa significa "logicamente correlato a una classe"? –

+0

@AndyT: beh, la sua logica è fortemente legata a quella della classe. –

21

In C++, si sono in realtà incoraggiati a livello lingua da utilizzare un namespace piuttosto che un class contenente solo static metodi a causa della ricerca di Koenig (aka Argument Lookup Dependent).

Esempio:

namespace geometry { 
    struct Point { int x, y; }; 

    double distance_from_center(Point const& p) { 
     return sqrt(p.x * p.x + p.y + p.y); 
    } 
} // namespace geometry 

int main() { 
    geometry::Point const p{3, 4}; // must qualify 

    std::cout << distance_from_center(p) << "\n"; // not qualified 
} 

Se distance_from_center è scritto come un metodo static in un class, allora avete bisogno di qualificare in modo esplicito ogni volta.

+1

Non lo sapevo mai! tuttavia essere esplicito lo renderebbe più leggibile – balki

+1

@balki: più leggibile o più disordinato? È sempre un buon equilibrio. Potrebbe essere un po 'abbagliante per i ragazzi di Java/C#, ma è idiomatico in C++ quindi non ci sono problemi. Inoltre, nel codice generico (modelli), è molto più semplice. –

8

E 'una domanda difficile e interessante per me personalmente, così ha deciso di condividere la mia modesta opinione

Considerando la differenza tra la classe "statica" (solo i membri statici) e namespace:

  1. uno spazio dei nomi può essere sparsi su più file: flessibilità aggiuntiva, ma dovrebbe essere usato con attenzione.
  2. uno spazio dei nomi fornisce argomento di ricerca dipendente (see Matthieu M. answer): utile in situazioni specifiche
  3. una classe "statica" può avere modificatori di accesso e può formare una gerarchia: Penso che i membri privati ​​dichiarati nella interfaccia di classe e visibile ai propri clienti è un Funzionalità C++ dettata più da ragioni tecniche, non logiche. Non vedo alcun beneficio dei membri statici privati. Membri protetti per la gerarchia "statica"? Mai visto nessuno.
  4. una classe "statica" può essere un "template", oltre ai membri di modello: vedi Steve Jessop's answer per un grande esempio da STL

Dal punto di vista della manutenzione, a volte si decide di fare una classe "static "(come un singleton), ma poi il requisito è cambiato e hai bisogno di più istanze. La classe "statica" sarebbe più semplice da trasformare rispetto al namespace.

E, infine, per rispondere alla tua domanda:

se non hai bisogno di particolari caratteristiche di classe "statica" o dello spazio dei nomi, utilizzare quello che ti piace di più :)

+0

Ora desidero disperatamente pensare a un uso per un membro protetto in una classe che ha solo membri statici. Forse una specie di situazione simile a CRTP, in cui una classe ha naturalmente una relazione speciale con le sue classi derivate? –

Problemi correlati