Comment créer une classe statique en C++?

comment créer une classe statique en C++? Je devrais pouvoir faire quelque chose comme:

cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;

en supposant que j'ai créé la classe BitParser . À quoi ressemblerait la définition de la classe BitParser ?

217
demandé sur Onur A. 2008-08-13 03:35:00

12 réponses

si vous cherchez un moyen d'appliquer le mot-clé" statique " à une classe, comme vous le pouvez en C# par exemple, alors vous ne pourrez pas le faire sans utiliser Managed C++.

mais l'apparence de votre échantillon, vous avez juste besoin de créer une méthode statique publique sur votre objet BitParser. Comme ceci:

BitParser.h

class BitParser
{
 public:
  static bool getBitAt(int buffer, int bitIndex);

  // ...lots of great stuff

 private:
  // Disallow creating an instance of this object
  BitParser() {}
};

BitParser.cpp

bool BitParser::getBitAt(int buffer, int bitIndex)
{
  bool isBitSet = false;
  // .. determine if bit is set
  return isBitSet;
}

Vous pouvez utiliser ce code pour appeler la méthode de la même manière que votre code d'exemple.

Espère que ça aide! Acclamation.

233
répondu OJ. 2016-07-25 17:32:02

prendre en considération Matt Prix de la solution .

  1. En C++, une "classe statique" n'a pas de sens. La chose la plus proche est une classe avec seulement des méthodes statiques et des membres.
  2. utilisant des méthodes statiques ne vous limitera.

ce que vous voulez, c'est, exprimé en sémantique C++, mettre votre fonction (car elle 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 seulement 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 sont pas capables d'avoir des fonctions non-membres, ils doivent donc les déplacer à l'intérieur des classes comme méthodes statiques.

en C++, ce que vous voulez vraiment est un fonction non-membre que vous déclarerez dans un espace de noms:

// header
namespace MyNamespace
{
   void myMethod() ;
}

// source
namespace MyNamespace
{
   void myMethod()
   {
      // etc.
   }
}

pourquoi?

en C++, l'espace de noms est plus puissant que les classes pour le motif "méthode statique Java", car:

  • les méthodes statiques ont accès aux classes symboles privés
  • les méthodes statiques privées sont encore visibles (si inaccessibles) à tout le monde, ce qui viole quelque peu l'encapsulation
  • méthodes statiques ne peuvent pas être l'avant-déclarée
  • 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
  • il n'y a rien qui puisse être fait par une méthode statique qui ne puisse être fait mieux qu'une fonction (éventuellement amie) non-membre dans le même espace de noms
  • Les namespaces
  • ont leur propre sémantique (ils peuvent être combinés, ils peuvent être anonymes, etc.)
  • etc.

Conclusion: ne pas copier / coller Ce modèle Java/C#en C++. En Java / C#, le modèle est obligatoire. Mais en C++, c'est un mauvais style.

Modifier 2010-06-10

il y avait un argument en faveur de la méthode statique parce que parfois, il faut utiliser une variable privée membre statique.

je suis en désaccord quelque peu, comme montré ci-dessous:

Le "Static private membre de la" solution

// HPP

class Foo
{
   public :
      void barA() ;
   private :
      void barB() ;
      static std::string myGlobal ;
} ;

tout d'abord, myGlobal est appelé myGlobal parce qu'il est encore une variable privée globale. Un regard sur la source du RPC permettra de clarifier 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 libre barC ne peut 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 sera pas capable (à moins de recourir au sabotage) d'accéder à Foo::myGlobal.

mais si vous regardez attentivement, vous verrez que c'est une erreur colossale: non seulement votre variable privée doit encore être déclarée dans le HPP (et donc, visible au monde entier, bien qu'étant privée), mais vous devez déclarer dans le même HPP toutes (comme en tout) les fonctions qui seront autorisées à y accéder !!!

So utiliser un membre statique privé, c'est comme sortir nu dehors avec la liste de vos amants tatouée sur votre peau : personne n'est autorisé à toucher, mais tout le monde est capable de coup d'oeil à. Et le bonus: tout le monde peut avoir les noms de ceux qui sont autorisés à jouer avec vos privies.

private en effet... :- D

Le "Anonyme espaces de noms" solution

les namespaces anonymes auront l'avantage de rendre les choses privées vraiment privées.

tout d'Abord, l'entraîneur de l'en-tête

// 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 veut dire que personne ne sait ce qui est caché derrière barA.

puis, le 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 !!!
}

comme vous pouvez le voir, comme la soi-disant déclaration de" classe statique", foo et fooB sont toujours en mesure d'accéder à myGlobal. Mais personne d'autre ne peut. Et personne d'autre que ce CPP ne sait que fooB et myGlobal existent!

contrairement à la" classe statique " marche sur le nu avec son carnet d'adresses tatoué sur sa peau l'espace de nom "anonyme" est entièrement habillé , qui semble tout à fait mieux encapsulé AFAIK.

est-ce vraiment important?

sauf si les utilisateurs de votre code sont des saboteurs (je vous laisse, comme un exercice, trouver comment on peut accéder à la partie privée d'une classe publique en utilisant un comportement sale-hack non défini...), ce qui est private est private , même si elle est visible dans l' private d'une classe déclarée dans l'en-tête.

cependant, si vous devez ajouter une autre " fonction privée "avec accès au membre privé, vous devez quand même la déclarer au monde entier en modifiant l'en-tête, ce qui est un paradoxe en ce qui me concerne: si je change l'implémentation de mon code (la partie CPP), alors l'interface (la partie HPP) ne devrait pas changer. citant Leonidas: " C'est L'ENCAPSULATION! "

Modifier 2014-09-20

quand les méthodes statiques de classes sont-elles réellement meilleures que les espaces de noms avec des fonctions non-membres?

quand vous avez besoin de grouper des fonctions et d'alimenter ce groupe à 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 template, un namespaces ne le peut pas.

213
répondu paercebal 2018-07-05 12:48:43

vous pouvez aussi créer une fonction libre dans un espace de noms:

Dans BitParser.h

namespace BitParser
{
    bool getBitAt(int buffer, int bitIndex);
}

Dans BitParser.cpp

namespace BitParser
{
    bool getBitAt(int buffer, int bitIndex)
    {
        //get the bit :)
    }
}

En général, ce qui serait la meilleure façon d'écrire le code. Quand il n'y a pas besoin d'un objet n'utilisez pas de classe.

58
répondu Matt Price 2008-08-13 00:26:43

si vous cherchez un moyen d'appliquer le mot-clé" statique "à une classe, comme vous pouvez dans C# par exemple

les classes statiques ne sont que le compilateur qui vous tient à la main et vous empêche d'écrire des méthodes/variables d'instance.

si vous écrivez juste une classe normale sans n'importe quelles méthodes/variables d'instance, c'est la même chose, et c'est ce que vous feriez en C++

12
répondu Orion Edwards 2008-08-13 00:06:09

En C++, vous souhaitez créer une fonction statique d'une classe (pas une classe statique).

class BitParser {
public:
  ...
  static ... getBitAt(...) {
  }
};

vous devriez alors pouvoir appeler la fonction en utilisant BitParser::getBitAt() sans instancier un objet qui je présume est le résultat désiré.

11
répondu Philip Reynolds 2008-08-12 23:43:34

puis-je écrire quelque chose comme static class ?

No , selon le C++11 N3337 standard draft Annexe C 7.1.1:

le Changement: En C ++, la statique ou extern prescripteurs ne peut être appliqué qu'à des noms d'objets ou de fonctions. Utiliser ces spécificateurs avec des déclarations de type est illégal en C ++. En C, ces spécificateurs sont ignorés quand ils sont utilisés sur type déclaration. Exemple:

static struct S {    // valid C, invalid in C++
  int i;
};

justification: les spécificateurs de classe de stockage n'ont aucun sens lorsqu'ils sont associés à un type. En C ++, class les membres peuvent être déclarés avec le spécificateur de classe de stockage statique. Possibilité de spécifier la classe de stockage sur le type les déclarations pourraient rendre le code confus pour les utilisateurs.

et comme struct , class est aussi une déclaration de type.

la même chose peut être déduite en parcourant l'arbre syntaxique de l'Annexe A.

Il est intéressant de noter que le static struct était légal en C, mais n'avait aucun effet: Pourquoi et quand utiliser des structures statiques dans la programmation en C?

10

Vous "peut" avoir une classe statique en C++, comme mentionné précédemment, une classe statique est celui qui ne dispose pas de tous les objets de instancié. En C++, ceci peut être obtenu en déclarant le constructeur/destructeur comme privé. Résultat final est le même.

5
répondu Netzer 2009-11-23 21:04:27

en C++ géré, la syntaxe de classe statique est: -

public ref class BitParser abstract sealed
{
    public:
        static bool GetBitAt(...)
        {
            ...
        }
}

... mieux vaut tard que jamais...

4
répondu Malc B 2010-06-10 15:35:29

c'est similaire à la façon de faire de C#en C++

Dans le fichier C#.cs vous pouvez avoir var privé à l'intérieur d'une fonction publique. Lorsque, dans un autre fichier, vous pouvez l'utiliser en appelant l'espace de noms avec la fonction comme dans:

MyNamespace.Function(blah);

Voici comment imp la même en C++:

SharedModule.h

class TheDataToBeHidden
{
  public:
    static int _var1;
    static int _var2;
};

namespace SharedData
{
  void SetError(const char *Message, const char *Title);
  void DisplayError(void);
}

SharedModule.cpp

//Init the data (Link error if not done)
int TheDataToBeHidden::_var1 = 0;
int TheDataToBeHidden::_var2 = 0;


//Implement the namespace
namespace SharedData
{
  void SetError(const char *Message, const char *Title)
  {
    //blah using TheDataToBeHidden::_var1, etc
  }

  void DisplayError(void)
  {
    //blah
  }
}

OtherFile.h

#include "SharedModule.h"

Other File.cpp

//Call the functions using the hidden variables
SharedData::SetError("Hello", "World");
SharedData::DisplayError();
3
répondu John 2010-04-27 02:38:36

contrairement à d'autres langages de programmation gérés, "static class" n'a pas de sens en C++. Vous pouvez utiliser une fonction membre statique.

3
répondu Bharath Ravindra 2014-01-29 06:34:41

comme il a été noté ici, une meilleure façon d'y parvenir en C++ pourrait être d'utiliser des espaces de noms. Mais puisque personne n'a mentionné le mot-clé final ici, je poste ce qu'un équivalent direct de static class de C# ressemblerait dans C++11 ou plus tard:

class BitParser final
{
public:
  BitParser() = delete;

  static bool GetBitAt(int buffer, int pos);
};

bool BitParser::GetBitAt(int buffer, int pos)
{
  // your code
}
1
répondu Mikhail Vasilyev 2018-03-21 11:52:10

un cas où les espaces de noms peuvent ne pas être aussi utiles pour réaliser des "classes statiques" est lorsque l'on utilise ces classes pour obtenir la composition par rapport à l'héritage. Les Namespaces ne peuvent pas être des amis de classe et ne peuvent donc pas accéder aux membres privés d'une classe.

class Class {
 public:
  void foo() { Static::bar(*this); }    

 private:
  int member{0};
  friend class Static;
};    

class Static {
 public:
  template <typename T>
  static void bar(T& t) {
    t.member = 1;
  }
};
0
répondu Josh Olson 2018-04-25 07:47:11