Considera la soluzione di Matt Price .
- In C ++, una "classe statica" non ha significato. La cosa più vicina è una classe con solo metodi e membri statici.
- L'uso di metodi statici ti limiterà.
Quello che vuoi è, espresso in semantica C ++, per mettere la tua funzione (perché è una funzione) in uno spazio dei nomi.
Modifica 2011-11-11
Non esiste una "classe statica" in C ++. Il concetto più vicino sarebbe una classe con solo metodi statici. Per esempio:
// header
class MyClass
{
public :
static void myMethod() ;
} ;
// source
void MyClass::myMethod()
{
// etc.
}
Ma devi ricordare che le "classi statiche" sono hack nei linguaggi simili a Java (es. C #) che non sono in grado di avere funzioni non membri, quindi devono invece spostarle all'interno delle classi come metodi statici.
In C ++, ciò che vuoi veramente è una funzione non membro che dichiarerai in uno spazio dei nomi:
// header
namespace MyNamespace
{
void myMethod() ;
}
// source
namespace MyNamespace
{
void myMethod()
{
// etc.
}
}
Perché?
In C ++, lo spazio dei nomi è più potente delle classi per il modello "Metodo statico Java", perché:
- i metodi statici hanno accesso ai simboli privati delle classi
- i metodi statici privati sono ancora visibili (se inaccessibili) a tutti, il che viola in qualche modo l'incapsulamento
- i metodi statici non possono essere dichiarati in avanti
- i metodi statici non possono essere sovraccaricati dall'utente della classe senza modificare l'intestazione della libreria
- non c'è nulla che possa essere fatto con un metodo statico che non può essere fatto meglio di una funzione non membro (possibilmente amico) nello stesso spazio dei nomi
- gli spazi dei nomi hanno la loro semantica (possono essere combinati, possono essere anonimi, ecc.)
- eccetera.
Conclusione: non copiare / incollare il modello di Java / C # in C ++. In Java / C #, il modello è obbligatorio. Ma in C ++, è cattivo stile.
Modifica 10/06/2010
C'è stato un argomento a favore del metodo statico perché a volte, è necessario utilizzare una variabile membro privata statica.
Non sono abbastanza d'accordo, come mostrato di seguito:
La soluzione "Membro privato statico"
// HPP
class Foo
{
public :
void barA() ;
private :
void barB() ;
static std::string myGlobal ;
} ;
Innanzitutto, myGlobal si chiama myGlobal perché è ancora una variabile privata globale. Uno sguardo alla fonte CPP chiarirà che:
// CPP
std::string Foo::myGlobal ; // You MUST declare it in a CPP
void Foo::barA()
{
// I can access Foo::myGlobal
}
void Foo::barB()
{
// I can access Foo::myGlobal, too
}
void barC()
{
// I CAN'T access Foo::myGlobal !!!
}
A prima vista, il fatto che la barra delle funzioni libere C non riesca ad accedere a Foo :: myGlobal sembra una buona cosa dal punto di vista dell'incapsulamento ... È bello perché qualcuno che guarda l'HPP non sarà in grado (se non ricorrendo al sabotaggio) di accedere foo :: myglobal.
Ma se lo guardi da vicino, scoprirai che si tratta di un colossale errore: non solo la tua variabile privata deve ancora essere dichiarata nell'HPP (e quindi, visibile a tutto il mondo, nonostante sia privata), ma devi dichiarare nella stessa HPP tutte le funzioni (come in TUTTI) che saranno autorizzate ad accedervi !!!
Quindi usare un membro statico privato è come camminare fuori nel nudo con l'elenco dei tuoi amanti tatuato sulla pelle: nessuno è autorizzato a toccare, ma tutti sono in grado di sbirciare. E il bonus: tutti possono avere i nomi di quelli autorizzati a giocare con i tuoi privati.
private
anzi ... MrGreen
La soluzione "Spazi dei nomi anonimi"
Gli spazi dei nomi anonimi avranno il vantaggio di rendere le cose private davvero private.
Innanzitutto, l'intestazione HPP
// HPP
namespace Foo
{
void barA() ;
}
Solo per essere sicuri di aver osservato: non esiste una dichiarazione inutile di barB né myGlobal. Ciò significa che nessuno che legge l'intestazione sa cosa si nasconde dietro la barraA.
Quindi, il CPP:
// CPP
namespace Foo
{
namespace
{
std::string myGlobal ;
void Foo::barB()
{
// I can access Foo::myGlobal
}
}
void barA()
{
// I can access myGlobal, too
}
}
void barC()
{
// I STILL CAN'T access myGlobal !!!
}
Come puoi vedere, come la cosiddetta dichiarazione "classe statica", fooA e fooB sono ancora in grado di accedere a myGlobal. Ma nessun altro può. E nessun altro al di fuori di questo CPP sa che esistono fooB e myGlobal!
A differenza della "classe statica" che cammina sul nudo con la sua rubrica tatuata sulla pelle, lo spazio dei nomi "anonimo" è completamente vestito , il che sembra piuttosto incapsulato AFAIK.
Importa davvero?
A meno che gli utenti del vostro codice sono sabotatori (Ti lascerò, come esercizio, scopri come si può accedere alla parte privata di una classe pubblica utilizzando un hack comportamento non definito sporca ...), ciò che è private
è private
, anche se è visibile nella private
sezione di una classe dichiarata in un'intestazione.
Tuttavia, se è necessario aggiungere un'altra "funzione privata" con accesso al membro privato, è comunque necessario dichiararlo a tutto il mondo modificando l'intestazione, che è un paradosso per quanto mi riguarda: se cambio l'implementazione di il mio codice (la parte CPP), quindi l'interfaccia (la parte HPP) NON dovrebbe cambiare. Citando Leonidas: " Questo è ENCAPSULATION! "
Modifica 20/09/2014
Quando i metodi statici delle classi sono effettivamente migliori degli spazi dei nomi con funzioni non membro?
Quando è necessario raggruppare le funzioni e alimentare quel gruppo in un modello:
namespace alpha
{
void foo() ;
void bar() ;
}
struct Beta
{
static void foo() ;
static void bar() ;
};
template <typename T>
struct Gamma
{
void foobar()
{
T::foo() ;
T::bar() ;
}
};
Gamma<alpha> ga ; // compilation error
Gamma<Beta> gb ; // ok
gb.foobar() ; // ok !!!
Perché, se una classe può essere un parametro modello, uno spazio dei nomi non può.