简体   繁体   中英

Using a namespace in place of a static class in C++?

Is it good or okay practice to use a namespace as a static class? For example:

namespace MyStaticFunctions {
    void doSomething();
}

Versus:

class MyStaticFunctions {
    static void doSomething();
}

There's no such thing as a "static class" in C++, so from a C++ point of view you're not using it "as a static class", you're using it "as a namespace". It's certainly accepted practice to use namespaces to group functions together.

It's up to you, though, how big you want the groups to be. It's not unusual for C++ libraries to use a single namespace for the whole public interface. That might come as a surprise to someone who is used to (say) Java, where classes are often used to group together smaller numbers of static methods. Since C++ was here first, you could say that Java is using classes as namespaces.

So, in C++ you don't tend to see classes similar to java.util.Collections or java.lang.Math , full of static members. If you want groups of functions like that in C++, use namespaces.

The exception (isn't there always a special case in C++?) is traits types like std::numeric_limits<T> , where the template parameter makes the class do something that a namespace can't do. You could define a namespace numeric_limits containing function templates max<T>() , min<T>() etc, but it's not as good. Firstly, it groups things slightly differently, the type T appears "lower down the hierarchy". Secondly it doesn't do everything that a traits type does, because there's no such thing as an "object template" that would let you define a value numeric_limits::digits<T> .

I don't know C# well enough to comment on the practical uses of static classes there, but AFAIK it's just a class restricted to having no non-static members, so it's analogous to those Java classes.

In C++, you are actually encouraged at the language level to use a namespace rather than a class containing only static methods because of Koenig's lookup (aka Argument Dependent Lookup).

Example:

namespace geometry {
    struct Point { int x, y; };

    double distance_from_center(Point const& p) {
        return sqrt(p.x * p.x + p.y + p.y);
    }
} // namespace geometry

int main() {
    geometry::Point const p{3, 4}; // must qualify

    std::cout << distance_from_center(p) << "\n"; // not qualified
}

If distance_from_center is written as a static method in a class , then you need to explicitly qualify it each time.

It's a tough and interesting question for me personally, so decided to share my humble opinion

Considering the difference between "static" class (only static members) and namespace:

  1. a namespace can be scattered over multiple files: additional flexibility but should be used carefully.
  2. a namespace provides argument dependent lookup ( see Matthieu M. answer ): useful in specific situations
  3. a "static" class can have access modifiers and can form an hierarchy: I think private members declared in class interface and visible to its clients is a C++ feature that was dictated more by technical, not logical reasons. I don't see any benefits of private static members. Protected members for "static" hierarchy? Never seen any.
  4. a "static" class can be a "template", in addition to template members: see Steve Jessop's answer for a great example from STL

From maintenance point of view, sometimes you decide to make a class "static" (like a singleton), but then requirement changed and you need multiple instances. "Static" class would be easier to transform than namespace.

And, finally, to answer your question:

if you don't need special features of "static" class or namespace, use what you like more :)

It depends.

Is the method logically related to a class? If so, make it a member, otherwise place it in a namespace.

Functionally, they're the same, but there's more to code than function, right? For example, consider a method that returns the name of the class:

struct MyClass
{
    static std::string getName() { return "MyClass"; }
}

You could obviously place the method outside, in a namespace , and get the same result, but it logically belongs to the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM