Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Are classes with only static members bad practice/anti-pattern?

Tags:

c++

class

static

Regarding classes that only contain static members, I've seen multiple people claiming that it is a bad pattern and that it's never the best solution to a problem.

The accepted and top-voted answer on Are utility classes with nothing but static members an anti-pattern in C++? advocates using namespaces instead and concludes by stating

the most obvious answer to me is: Because we don't need OO to achieve this.

This is strange to me for several reasons. It seems like they are talking about classes only containing static member functions, and not classes containing a mix of static data and static functions. Classes with only static member functions can indeed be replaced with global functions inside a namespace, but how would you replace a class with containing both static functions and static data?

struct Foo
{
    static void add5()
    {
        s_x += 5;
    }
    static const int& getX()
    {
        return s_x;
    }
private:
    static int s_x;
};
int Foo::s_x{ 0 };

With functions and a global variable inside a namespace? How would you make sure s_x can't be accessed directly and modified by outside code?

The other thing that confuses me is that I feel like classes with only static members are a fairly common occurrence in books on C++ and in libraries.

SFML's sf::Mouse has only static members.

Game Programming Patterns uses classes with only static members several times, even referring to it with the term "static class" in the Singleton chapter. And the Service Locator chapter is inherently a class with only static members.

So how should one think? Are classes with only static members bad design / bad practice? Or do they have their place in some contexts?

like image 421
JensB Avatar asked Sep 17 '25 13:09

JensB


1 Answers

The top answer of the other question still holds: you do not need classes to encapsulate static functions and static variables. This can be done with namespaces and -- with a little discipline -- using the scope of compilation units.

In your example, you do not need to expose the existence of a private static data member if you're using namespaces:

Declare in a header:

namespace Foo {
    void add5();
    const int& getX();
}

Then implement in a cpp:

namespace Foo
{
    static int s_x{0};   // static globals are not visible outside the compilation unit

    void add5()
    {
        s_x += 5;
    }
    const int& getX()
    {
        return s_x;
    }
};

Be careful: static globals are not exactly the same thing than static members, but in the code above, it's the same effect as it's private. For public data members, you'd just remove the keyword static.

like image 185
Christophe Avatar answered Sep 20 '25 04:09

Christophe