views:

21841

answers:

9

How do you create a static class in C++? I should be able to do something like:

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

Assuming I created the BitParser class. What would the BitParser class definition look like?

+3  A: 

In C++ you want to create a static function of a class (not a static class).

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

You should then be able to call the function using BitParser::getBitAt() without instantiating an object which I presume is the desired result.

Phil
+26  A: 

If you're looking for a way of applying the "static" keyword to a class, like you can in C# for example, then you won't be able to without using Managed C++.

But the looks of your sample, you just need to create a public static method on your BitParser object. Like so:

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

  // .. lots of great stuff
};

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

You can use this code to call the method in the same way as your example code.

Hope that helps! Cheers.


Edit: SuperJoe - Thanks mate! Fixed it up. Poor form eh? :)

OJ
To make your intention clear in this approach you can additionally use a private constructor. `private: BitParser() {}` This will prevent anyone from creating instances.
Danvil
+3  A: 

If you're looking for a way of applying the "static" keyword to a class, like you can in C# for example

static classes are just the compiler hand-holding you and stopping you from writing any instance methods/variables.

If you just write a normal class without any instance methods/variables, it's the same thing, and this is what you'd do in C++

Orion Edwards
+17  A: 

You can also create a free function in a namespace:

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 general this would be the preferred way to write the code. When there's no need for an object don't use a class.

Matt Price
In some cases you may want to have data encapsulation even if the class is mostly "static". Static private class members will give you this. Namespace members are always public and cannot provide data encapsulation.
Torleif
If the "member" var is only declared and accessed from the .cpp file, it is more private than a private var declared in the .h file. NOT that I recommend this technique.
jmucchiello
@Torleif : You're wrong. namespaces are better for encapsulation than static private members. See my answer for demonstration.
paercebal
+1  A: 

OJ, you have a syntax error.

The static keyword should only be used in the class definition, and not in the method definition.

superjoe30
+7  A: 

Consider Matt Price's solution.

In C++, a "static class" has no meaning. Using static methods will only limit you.

What you want is, expressed in C++ semantics, to put your function (for it is a function) in a namespace.

Edit

There was an argument in favor to the static method because sometimes, one needs to use a static private member variable.

I disagree somewhat, as show below:

The "Static private member" solution

// HPP

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

First, myGlobal is called myGlobal because it is still a global private variable. A look at the CPP source will clarify that:

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

At first sight, the fact the free function barC can't access Foo::myGlobal seems a good thing from an encapsulation viewpoint... It's cool because someone looking at the HPP won't be able (unless resorting to sabotage) to access Foo::myGlobal.

But if you look at it closely, you'll find that it is a colossal mistake: Not only your private variable must still be declared in the HPP (and so, visible to all the world, despite being private), but you must declare in the same HPP all (as in ALL) functions that will be authorized to access it !!!

So using a private static member is like walking outside in the nude with the list of your lovers tattooed on your skin : No one is authorized to touch, but everyone is able to peek at. And the bonus: Everyone can have the names of those authorized to play with your privies.

private indeed... :-D

The "Anonymous namespaces" solution

Anonymous namespaces will have the advantage of making things private really private.

First, the HPP header

// HPP

namespace Foo
{
   void barA() ;
}

Just to be sure you remarked: There is no useless declaration of barB nor myGlobal. Which means that no one reading the header knows what's hidden behind barA.

Then, the 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 !!!
}

As you can see, like the so-called "static class" declaration, fooA and fooB are still able to access myGlobal. But no one else can. And no one else outside this CPP knows fooB and myGlobal even exist!

Unlike the "static class" walking on the nude with her address book tattooed on her skin the "anonymous namespace is fully clothed, which seems quite better encapsulated AFAIK.

Does it really matter?

Unless the users of your code are saboteurs (I'll let you, as an exercise, find how one can access to the private part of a public class using a dirty behaviour-undefined hack...), what's private is private, even if it is visible in the private section of a class declared in a header.

Still, if you need to add another "private function" with access to the private member, you still must declare it to all the world by modifying the header, which is a paradox as far as I am concerned: If I change the implementation of my code (the CPP part), then the interface (the HPP part) should NOT change. Quoting Leonidas : "This is ENCAPSULATION!"

paercebal
GCC supports -fno-access-control, which can be used in whitebox unit tests to access otherwise private class members. That's about the only reason I can think of to justify using a class member instead of an anonymous/static global in the implementation.
Tom
@Tom: A cross-platform solution would be to add the following code `#define private public` in the headers... ^_^ ...
paercebal
@Tom: anyway, IMHO, even considering unit testing, the cons of "showing too much stuff" outweights the pros. I guess an alternative solution would be to put the code to be tested in a function taking the needed parameters (and no more) in a `utilities` namespace. This way, this function can be unit-tested, and still have no special access to private members (as they are given as parameters at the function call)...
paercebal
A: 

You 'can' have a static class in C++, as mentioned before, a static class is one that does not have any objects of it instantiated it. In C++, this can be obtained by declaring the constructor/destructor as private. End result is the same.

Netzer
A: 

This is similar to C#'s way of doing it in C++

In C# file.cs you can have private var inside a public function. When in another file you can use it by calling the namespace with the function as in:

MyNamespace.Function(blah);

Here's how to imp the same 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();
John
+1  A: 

In Managed C++, static class syntax is:-

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

... better late than never...

Malc B