Vra

Hoe skep jy'n statiese klas in C++?Ek moet in staat wees om iets te doen soos:

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

Die veronderstelling ek het die BitParser die klas.Wat sou die BitParser klas definisie lyk?

Was dit nuttig?

Oplossing

As jy op soek is na 'n manier van die toepassing van die "statiese" navraag aan 'n klas, soos jy kan in C # byvoorbeeld, dan sal jy nie in staat wees om sonder die gebruik van Managed C ++.

Maar die lyk van jou monster, jy hoef net 'n openbare statiese metode op jou BitParser voorwerp te skep. Soos so:

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

Jy kan hierdie kode gebruik om die metode te roep in die dieselfde manier as jou voorbeeld kode.

Hoop dit help! Cheers.

Ander wenke

Oorweeg Matt Prys se oplossing.

  1. In C++, 'n "statiese klas" het geen betekenis nie.Die naaste ding is'n klas met net statiese metodes en lede.
  2. Met behulp van statiese metodes sal slegs beperk jou.

Wat jy wil hê, is, uitgedruk in C++ semantiek, om jou funksie (vir dit is 'n funksie) in'n namespace.

Wysig 2011-11-11

Daar is geen "statiese klas" in C++.Die naaste konsep sou'n klas met net statiese metodes.Byvoorbeeld:

// header
class MyClass
{
   public :
      static void myMethod() ;
} ;

// source
void MyClass::myMethod()
{
   // etc.
}

Maar jy moet onthou dat die "statiese klasse" is hacks in die Java-soos soort van tale (bv.C#) wat nie in staat is om te hê nie-lid funksies, sodat hulle het in plaas daarvan om hulle te beweeg binne-in klasse as statiese metodes.

In C++, wat jy regtig wil hê, is'n nie-lid van die funksie wat jy sal verklaar in'n namespace:

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

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

Hoekom is dat?

In C++, die namespace is meer kragtig as die klasse vir die "Java statiese metode" patroon, want:

  • statiese metodes het toegang tot die klasse private simbole
  • private statiese metodes is nog sigbaar (as ontoeganklik) aan almal, wat oortredings bietjie die inkapseling
  • statiese metodes kan nie vorentoe-verklaar
  • statiese metodes kan oorlaai word deur die klas gebruiker sonder die wysiging van die biblioteek kop
  • daar is niks wat gedoen kan word deur'n statiese metode wat nie gedoen kan word nie beter as'n (moontlik vriend) nie-lid funksie in die dieselfde namespace
  • namespace het hul eie semantiek (hulle kan gekombineer word, kan hulle anoniem, ens.)
  • ens.

Gevolgtrekking:Moenie kopie/plak dat Java/C#'s patroon in C++.In Java/C#, die patroon is verpligtend.Maar in C++, dit is slegte styl.

Wysig 2010-06-10

Daar was'n argument ten gunste van die statiese metode, want soms moet'n mens gebruik'n statiese private lid veranderlike.

Ek verskil bietjie, as show hieronder:

Die "Statiese private lid" oplossing

// HPP

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

Eerste, myGlobal genoem myGlobal want dit is nog steeds'n globale private veranderlike.'n blik op die CPP bron sal verduidelik dat:

// 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 !!!
}

Met die eerste oogopslag, die feit dat die vrye funksie barC kan nie toegang tot Cat::myGlobal lyk na'n goeie ding van'n inkapseling standpunt...Dit is cool, want iemand soek op die HPP nie in staat sal wees (tensy wend om sabotasie) om toegang te verkry Cat::myGlobal.

Maar as jy kyk na dit nou, jy sal vind dat dit is'n reuse-fout:Nie net jou private veranderlike nog moet verklaar word in die HPP (en so, sigbaar aan die hele wêreld, ten spyte van die feit dat private), maar jy moet verklaar in die dieselfde HPP al (soos in AL) funksies wat sal gemagtig word om dit te bekom !!!

So met behulp van'n private statiese lid is soos loop buite in die kaal met die lys van jou geliefdes getatoeëer op jou vel :Niemand is gemagtig om aan te raak, maar almal is in staat om te loer by.En die bonus:Almal kan die name van diegene wat gemagtig is om te speel met jou privies.

private inderdaad...:-D

Die "Anonieme namespace" oplossing

Anoniem namespace sal die voordeel van die maak van dinge private baie privaat.

Eerste, die HPP kop

// HPP

namespace Foo
{
   void barA() ;
}

Net om seker te wees jy opgemerk:Daar is geen nutteloos verklaring van barB of myGlobal.Wat beteken dat geen een die lees van die kop weet wat is weggesteek agter barA.

Dan, die 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 !!!
}

Soos jy kan sien, soos die so-genoem "statiese klas" verklaring, fooA en fooB is nog steeds in staat om toegang te verkry myGlobal.Maar niemand anders kan.En niemand anders nie buite hierdie CPP weet fooB en myGlobal eens bestaan nie!

In teenstelling met die "statiese klas" loop op die kaal met haar adres boek getatoeëer op haar vel, die "anonieme" namespace is ten volle geklee, wat lyk baie beter saamgevat AFAIK.

Maak dit regtig saak?

Tensy die gebruikers van jou kode is saboteurs (ek sal laat jy, as'n oefening, vind hoe kan'n mens toegang tot die private deel van'n openbare klas met behulp van'n vuil gedrag-ongedefinieerde hack...), wat se private is private, selfs as dit is sigbaar in die private gedeelte van'n klas verklaar in'n kop.

Nog steeds, as jy nodig het om te voeg nog'n "private funksie" met toegang tot die private lid, jy moet nog steeds verklaar dit aan die hele wêreld deur die wysiging van die kop, wat is'n paradoks so ver as ek is bekommerd: As ek die implementering van my kode (die CPP deel), dan is die koppelvlak (die HPP deel) moet nie verander NIE. Met Vermelding Van Leonidas :"Dit is die INKAPSELING!"

Wysig 2014-09-20

Wanneer klasse statiese metodes is eintlik beter as namespace met nie-lid funksies?

Wanneer jy nodig het om te groep saam funksies en voed die groep om'n sjabloon:

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 !!!

Want, as'n klas kan'n sjabloon parameter, 'n namespace nie.

Jy kan ook 'n gratis funksie te skep in 'n naamruimte:

In BitParser.h

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

In BitParser.cpp

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

In die algemeen sou die voorkeur manier om die kode te skryf. Wanneer daar is geen behoefte aan 'n voorwerp gebruik nie 'n klas.

  

As jy op soek is na 'n manier van die toepassing van die "statiese" navraag aan 'n klas, soos jy kan in C # byvoorbeeld

statiese klasse is net die samesteller hand-hou jy en stop jy van die skryf van enige instansie metodes / veranderlikes.

As jy net skryf 'n normale klas sonder enige instansie metodes / veranderlikes, dit is dieselfde ding, en dit is wat jy wil doen in C ++

In C ++ wat jy wil 'n statiese funksie van 'n klas (nie 'n statiese klas).

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

Jy moet dan in staat wees om die funksie met behulp van BitParser :: getBitAt () noem sonder instantiëren 'n voorwerp wat ek vermoed is die gewenste resultaat.

Kan ek skryf iets soos static class?

Geen , volgens die C ++ 11 N3337 standaard konsep aanhangsel C 7.1.1:

  

Verandering: In C ++, kan die statiese of eksterne spesifiseerders net toegepas word op name van voorwerpe of funksies.   Die gebruik van hierdie spesifiseerders met tipe verklarings is onwettig in C ++. In C, is hierdie spesifiseerders geïgnoreer wanneer dit gebruik word   op tipe verklarings. Byvoorbeeld:

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

Rasionaal: Storage klas spesifiseerders nie enige betekenis hê wanneer wat verband hou met 'n tipe. In C ++, klas   lede kan verklaar word met die statiese stoor klas specific. Sodat stoor klas spesifiseerders op tipe   verklarings kon die kode te lewer verwarrend vir gebruikers.

En soos struct, class is ook 'n tipe verklaring.

Dieselfde kan afgelei word deur die loop van die sintaksis boom in aanhangsel A.

Dit is interessant om daarop te let dat static struct was reg in C, maar het geen effek gehad: Hoekom en wanneer om statiese strukture gebruik in C programmering?

Jy 'kan' 'n statiese klas in C ++, soos voorheen genoem, 'n statiese klas is een wat nie enige voorwerpe het nie daarvan aangehaal dit. In C ++, kan dit verkry word deur te verklaar die konstruktor / destructor as private. Eindresultaat is dieselfde.

In Bestuurde C ++, statiese klas sintaksis is: -

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

... beter laat as nooit ...

Dit is soortgelyk aan manier van doen dit in C ++

C # 's

In C # file.cs jy kan private var binne 'n openbare funksie het. Wanneer in 'n ander lêer wat jy dit kan gebruik word deur die roeping van die naamruimte met die funksie as in:

MyNamespace.Function(blah);

Hier is hoe om dieselfde imp in 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"

OtherFile.cpp

//Call the functions using the hidden variables
SharedData::SetError("Hello", "World");
SharedData::DisplayError();

In teenstelling met ander bestuur programmeertaal, "statiese klas" het geen betekenis in C ++. Jy kan gebruik maak van statiese lid funksie maak.

As dit hier aangeteken, kan 'n beter manier om dit te bereik in C ++ wees met behulp van naamruimtes. Maar omdat niemand hier het genoem die final navraag, ek plaas wat 'n direkte ekwivalent van static class van C # sou lyk in C ++ 11 of later:

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

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

bool BitParser::GetBitAt(int buffer, int pos)
{
  // your code
}

Een geval waar naamruimtes nie so nuttig vir die bereiking van "statiese klasse" kan wees, is wanneer die gebruik van hierdie klasse aan samestelling oor erfenis te bereik. Naamruimtes kan nie vriende van klasse wees en kan dus nie toegang tot private lede van 'n klas.

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;
  }
};
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top