Considérez la solution de Matt Price .
- En C ++, une "classe statique" n'a pas de sens. La chose la plus proche est une classe avec uniquement des méthodes et des membres statiques.
- L'utilisation de méthodes statiques ne fera que vous limiter.
Ce que vous voulez est exprimé dans la sémantique C, pour mettre votre fonction (car il est une fonction) dans un espace de noms.
Modifier 2011-11-11
Il n'y a pas de "classe statique" en C ++. Le concept le plus proche serait une classe avec uniquement des méthodes statiques. Par exemple:
// header
class MyClass
{
public :
static void myMethod() ;
} ;
// source
void MyClass::myMethod()
{
// etc.
}
Mais vous devez vous rappeler que les "classes statiques" sont des hacks dans les langages de type Java (par exemple C #) qui ne peuvent pas avoir de fonctions non membres, donc ils doivent plutôt les déplacer à l'intérieur des classes en tant que méthodes statiques.
En C ++, ce que vous voulez vraiment, c'est une fonction non membre que vous déclarerez dans un espace de noms:
// header
namespace MyNamespace
{
void myMethod() ;
}
// source
namespace MyNamespace
{
void myMethod()
{
// etc.
}
}
Pourquoi donc?
En C ++, l'espace de noms est plus puissant que les classes pour le modèle "Java static method", car:
- les méthodes statiques ont accès aux symboles privés des classes
- les méthodes statiques privées sont toujours visibles (si inaccessibles) pour tout le monde, ce qui viole quelque peu l'encapsulation
- les méthodes statiques ne peuvent pas être déclarées en aval
- les méthodes statiques ne peuvent pas être surchargées par l'utilisateur de la classe sans modifier l'en-tête de la bibliothèque
- rien ne peut être fait par une méthode statique qui ne peut pas être fait mieux qu'une fonction non-membre (peut-être un ami) dans le même espace de noms
- les espaces de noms ont leur propre sémantique (ils peuvent être combinés, ils peuvent être anonymes, etc.)
- etc.
Conclusion: ne copiez / collez pas le modèle Java / C # en C ++. En Java / C #, le modèle est obligatoire. Mais en C ++, c'est du mauvais style.
Modifier le 2010-06-10
Il y avait un argument en faveur de la méthode statique, car parfois, il faut utiliser une variable de membre privé statique.
Je suis en désaccord quelque peu, comme indiqué ci-dessous:
La solution "Membre Privé Statique"
// HPP
class Foo
{
public :
void barA() ;
private :
void barB() ;
static std::string myGlobal ;
} ;
Tout d'abord, myGlobal est appelé myGlobal car il s'agit toujours d'une variable privée globale. Un regard sur la source du RPC clarifiera que:
// 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 !!!
}
À première vue, le fait que la fonction gratuite barC ne puisse pas accéder à Foo :: myGlobal semble une bonne chose du point de vue de l'encapsulation ... C'est cool parce que quelqu'un qui regarde le HPP ne pourra pas (sauf s'il a recours au sabotage) accéder Foo :: myGlobal.
Mais si vous y regardez de près, vous constaterez que c'est une erreur colossale: non seulement votre variable privée doit toujours être déclarée dans le HPP (et donc, visible par le monde entier, bien qu'elle soit privée), mais vous devez déclarer dans le même HPP toutes les fonctions (comme dans TOUS) qui seront autorisées à y accéder !!!
Donc, utiliser un membre statique privé, c'est comme marcher dehors nu avec la liste de vos amants tatoués sur votre peau: Personne n'est autorisé à toucher, mais tout le monde peut y jeter un œil. Et le bonus: tout le monde peut avoir les noms des personnes autorisées à jouer avec vos amis.
private
en effet ... :-D
La solution "espaces de noms anonymes"
Les espaces de noms anonymes auront l'avantage de rendre les choses privées vraiment privées.
Tout d'abord, l'en-tête HPP
// HPP
namespace Foo
{
void barA() ;
}
Juste pour être sûr que vous avez remarqué: il n'y a pas de déclaration inutile de barB ni de myGlobal. Ce qui signifie que personne ne lisant l'en-tête ne sait ce qui se cache derrière barA.
Ensuite, le RPC:
// 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 !!!
}
Comme vous pouvez le voir, comme la déclaration dite de "classe statique", fooA et fooB peuvent toujours accéder à myGlobal. Mais personne d'autre ne le peut. Et personne d'autre en dehors de ce CPP ne sait que fooB et myGlobal existent même!
Contrairement à la "classe statique" marchant sur le nu avec son carnet d'adresses tatoué sur la peau, l'espace de noms "anonyme" est entièrement habillé , ce qui semble bien mieux encapsulé AFAIK.
Est-ce que c'est vraiment important?
À moins que les utilisateurs de votre code ne soient des saboteurs (je vous laisse, comme exercice, trouver comment on peut accéder à la partie privée d'une classe publique en utilisant un hack sale non défini ...), qu'est-ce qui private
se passe private
, même s'il est visible dans la private
section d'une classe déclarée dans un en-tête.
Pourtant, si vous avez besoin d'ajouter une autre "fonction privée" avec accès au membre privé, vous devez toujours la déclarer à tout le monde en modifiant l'en-tête, ce qui est un paradoxe en ce qui me concerne: si je change la mise en œuvre de mon code (la partie CPP), puis l'interface (la partie HPP) ne doit PAS changer. Citant Leonidas: " C'est de l'ENCAPSULATION! "
Modifier le 2014-09-20
Quand les classes les méthodes statiques sont-elles réellement meilleures que les espaces de noms avec des fonctions non membres?
Lorsque vous devez regrouper des fonctions et alimenter ce groupe dans un modèle:
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 !!!
Parce que, si une classe peut être un paramètre de modèle, les espaces de noms ne le peuvent pas.