355

Let's say I have, or am going to write, a set of related functions. Let's say they're math-related. Organizationally, should I:

  1. Write these functions and put them in my MyMath namespace and refer to them via MyMath::XYZ()
  2. Create a class called MyMath and make these methods static and refer to the similarly MyMath::XYZ()

Why would I choose one over the other as a means of organizing my software?

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
RobertL
  • 4,106
  • 4
  • 20
  • 7
  • 5
    for one thing, namespaces are more recent addition to the language, compared to classes and static methods, which were in the language from the time it was called "C with classes". Some programmers may be more comfortable with older features. Some other programmers may be using old compilers. Just my $.02 – Rom Sep 16 '09 at 19:19
  • 26
    @Rom: You're right about "old programmers", but wrong about "old compilers". Namespaces are correctly compiled since eons (I worked with them with Visual C++ 6, dating from 1998!). As for the "C with classes", some people in this forum weren't even born when that happened: Using this as an argument to avoid a standard and widespread C++ feature is a fallacy. In conclusion, only obsolete C++ compilers don't support namespaces. Don't use that argument as an excuse to not use them. – paercebal Sep 16 '09 at 20:10
  • 1
    @paercebal: some ancient compilers are still in use in embedded world. Not supporting namespaces is probably one of the smallest inconveniences one needs to put up with while writing code for various small CPUs which everyone interacts with every day: your stereo, your microwave, engine control unit in your car, traffic light, etc. Just to be clear: I'm not advocating for not using a better, newer compilers everywhere. Au conrare: I'm all for newest language features (except RTTI ;) ). I'm just pointing out that such a tendency exists – Rom Sep 16 '09 at 23:38
  • 14
    @Rom: In the current case, the question author has the choice, so apparently, none of his/her compilers fails to compile a namespaced code. And as this is a question about C++, a C++ answer must be given, including mentioning namespaces and RTTI solutions to the problem if needed. Giving a C answer, or a C-with-classes-for-obsolete-compilers answer is out of topic. – paercebal Jan 21 '11 at 18:19

9 Answers9

279

By default, use namespaced functions.

Classes are to build objects, not to replace namespaces.

In Object Oriented code

Scott Meyers wrote a whole Item for his Effective C++ book on this topic, "Prefer non-member non-friend functions to member functions". I found an online reference to this principle in an article from Herb Sutter: http://www.gotw.ca/gotw/084.htm

The important thing to know is that: In C++, functions that are in the same namespace as a class is, and that have that class as a parameter, belong to that class' interface (because ADL will search those functions when resolving function calls).

For example:

  • let's say you have a namespace N
  • let's say you have a class C, declared in namespace N (in other words, its full name is N::C)
  • let's say you have a function F, declared in namespace N (in other words, its full name is N::F)
  • let's say that function F has, among its parameters, a parameter of type C

... Then N::F is part of N::C's public interface.

Namespaced functions, unless declared "friend," have no access to the class's internals, whereas static methods have the right to access the class's internals.

This means, for example, that when maintaining your class, if you need to change your class' internals, you will need to search for side effects in all its methods, including the static ones.

Extension I

Adding code to a class' interface.

In C#, you can add methods to a class even if you have no access to it. But in C++, this is impossible.

But, still in C++, you can still add a namespaced function, even to a class someone wrote for you.

See from the other side, this is important when designing your code, because by putting your functions in a namespace, you will authorize your users to increase/complete the class' interface.

Extension II

A side-effect of the previous point, it is impossible to declare static methods in multiple headers. Every method must be declared in the same class.

For namespaces, functions from the same namespace can be declared in multiple headers (the almost-standard swap function is the best example of that).

Extension III

The basic coolness of a namespace is that in some code, you can avoid mentioning it, if you use the keyword using:

#include <string>
#include <vector>

// Etc.
{
   using namespace std ;
   // Now, everything from std is accessible without qualification
   string s ; // Ok
   vector v ; // Ok
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

And you can even limit the "pollution" to one class:

#include <string>
#include <vector>

{
   using std::string ;
   string s ; // Ok
   vector v ; // COMPILATION ERROR
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

This "pattern" is mandatory for the proper use of the almost-standard swap idiom.

And this is impossible to do with static methods in classes.

So, C++ namespaces have their own semantics.

But it goes further, as you can combine namespaces in a way similar to inheritance.

For example, if you have a namespace A with a function AAA, a namespace B with a function BBB, you can declare a namespace C, and bring AAA and BBB in this namespace with the keyword using.

You can even bring the full content of a namespace inside another, with using namespace, as shown with namespace D!

namespace A
{
   void AAA();
   void AAA2();
}

namespace B
{
   void BBB();
}

namespace C
{
   using A::AAA;
   using B::BBB;
}

namespace D
{
   using namespace A;
   using namespace B;
}

void foo()
{
   C::AAA();
   // C::AAA2(); // ERROR, won't compile
   C::BBB();
}

void bar()
{
   D::AAA();
   D::AAA2();
   D::BBB();
}

Conclusion

Namespaces are for namespaces. Classes are for classes.

C++ was designed so each concept is different, and is used differently, in different cases, as a solution to different problems.

Don't use classes when you need namespaces.

And in your case, you need namespaces.

John
  • 2,963
  • 11
  • 33
paercebal
  • 81,378
  • 38
  • 130
  • 159
  • Can this answer be applied to threads too, i.e. is it better to use namespaces rather than static methods for threads? – dashesy Feb 17 '12 at 17:31
  • 3
    @dashesy : *namespaces vs. static methods* have nothing to do with threads, so yes, namespaces are better because namespaces are almost always better then static methods. If one thing, static methods have access to class member variables, so they somehow have a lower encapsulation value than namespaces. And isolating data is even more important in threaded execution. – paercebal Feb 17 '12 at 17:41
  • @paercebal- thanks, I was using the static class methods for thread functions. Now I understand I was misusing class as namespace, so what do you think is the best approach to have multiple threads in one object? I have asked this question on SO too, I appreciate if you can shed some light (here or in the question itself) – dashesy Feb 17 '12 at 17:56
  • 1
    @dashesy : You are asking for trouble. What you want with different threads is to isolate the data that is not supposed to be shared, so having multiple threads having privilegied access to the private data of a class is a bad idea. I would hide **one** thread inside a class, and make sure to isolate the data for that thread from the data for the main thread. Of course, data that is supposed to be shared then can be members of that class, but they still should be synchronized (locks, atomic, etc.). I'm not sure about how much libs you have access to, but using tasks/async is even better. – paercebal Feb 17 '12 at 19:40
  • 1
    paercebal's answer should be the accepted one ! Just one more link for the almost standard swap() via namespace + ADL -> http://stackoverflow.com/questions/6380862/how-to-provide-a-swap-function-for-my-class – RoundPi Oct 04 '12 at 17:13
  • Could you explain more about how one would "add a namespaced function, even to a class"? The linked Sutter article seems to suggest that, e.g., std::string::erase should be outside of the class and be: `clear(std::string &s) { s.erase(s.begin(), s.end()); }`. Perhaps it's more extensible, but it's pretty darn annoying to have to check "do I do s.clear() or clear(s)?" for everything. Plus, it feels like object-oriented C. Perhaps I'm misunderstanding something? – prewett Feb 20 '14 at 10:58
  • @prewett : In CLISP, the invocation of functions (including "virtual" ones), is written `(funcname arg1 arg2 arg3)`, so the Java-like notation `arg1.funcname(arg2, arg3)` should not be taken as granted... Unlike Java and C#, in C++, functions are not dead. And once you get over that, the "annoying factor" takes a step back... I suggest you search SO for a question about "object.method()" vs. "method(object)" for C++, or ask it yourself, if you want a list of the merits/flaws of each notation. – paercebal Feb 21 '14 at 13:45
  • The Extension III seems to conflate using declarations (`using std::string;`) with using directives (`using namespace std;`) by not clearly separating them it may give the wrong impression, for the correct implementation of swap you *need* a using declaration. Personally I find using directives erroneous and not correctly understood by most people, you should avoid them. Specially if you mean to do what the last paragraph in this block suggests (bringing names from different namespaces together). – David Rodríguez - dribeas Jan 29 '15 at 16:15
  • @paercebal , If possible could you please paraphrase or elaborate on **In C++ functions in the same namespace as a class belong to that class' interface** ... I tried to understand this sentence but I think something is wrong with that (maybe it's missing a comma `','` somewhere). Sincere apology if the sentence is 100% right and I'm mistaken. In that case, would really appreciate your help, if you could paraphrase it a little bit. Thank you so much in advance! – Milan Nov 04 '20 at 02:10
  • @Milan: You're right about the fact this sentence wasn't clear. I've corrected it, and added an example. Please tell me if it is more clear, now. :-) – paercebal Nov 08 '20 at 13:38
  • @paercebal For C++, which one is better, "object.method()" or "method(object)"? – John Sep 08 '21 at 12:54
  • @John : Both. (sorry). Its complicated. Both style have overlapping features, but each enable features the other cannot enable. For example, "method(object)" enables static polymorphism via function overloading, so anyone can extend any type with that function. On the other hand, "object.method" cannot be extended (unless through inheritance), but enable runtime polymorphism. There's a whole list of pros/cons, some subjective, that exist. In other words, you should, perhaps, write a question on Stack Overflow, asking specifically for the objectives pros/cons to chose one over the other. – paercebal Sep 09 '21 at 14:30
  • @paercebal "Namespaced functions, unless declared "friend," have no access to the class' internals, whereas ***static methods*** have." ***Question***: which `static methods`, the static methods of the `class` or the static methods of the `namespace`? It would be more clear and appreciated that if you could show me a simple example. Thanks. – John Sep 12 '21 at 07:39
61

There are a lot of people who would disagree with me, but this is how I see it:

A class is essentially a definition of a certain kind of object. Static methods should define operations that are intimately tied to that object definition.

If you are just going to have a group of related functions not associated with an underlying object or definition of a kind of object, then I would say go with a namespace only. Just for me, conceptually, this is a lot more sensible.

For instance, in your case, ask yourself, "What is a MyMath?" If MyMath does not define a kind of object, then I would say: don't make it a class.

But like I said, I know there are plenty of folks who would (even vehemently) disagree with me on this (in particular, Java and C# developers).

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 3
    You have a very pure perspective on this. But practically speaking, a class with all-static methods can come in handy: you can `typedef` them, use them as template parameters, etc. – Shog9 Sep 16 '09 at 19:27
  • 62
    That's becuase Jave and C# people don't have a choice. – Martin York Sep 16 '09 at 19:27
  • 7
    @shog9. You can templatize functions as well! – Martin York Sep 16 '09 at 19:28
  • @Martin: Well yeah, of course. I guess my point is that the tools you use tend to shape the way you think. – Dan Tao Sep 16 '09 at 19:30
  • @Martin York: can you pass a namespace as a template parameter? – Shog9 Sep 16 '09 at 19:31
  • @Shog9: I think if somebody's interested in using a class as a template parameter, that class is almost surely defining some underlying object. Take this question as an example: What kind of template function would take MyMath as a parameter? – Dan Tao Sep 16 '09 at 19:35
  • 6
    @Dan: presumably, one that needed math routines and wanted to support "plugging in" different implementations. – Shog9 Sep 16 '09 at 19:37
  • @Shog9: That isn't to say I don't appreciate your pragmatic take, though. The additional benefits of using a static class are certainly not nothing. – Dan Tao Sep 16 '09 at 19:37
  • @Dan: and by the same token, i'm not trying to *promote* static classes here - they *are* over-used, at least in much of the code i've seen. But they do have their uses. – Shog9 Sep 16 '09 at 19:38
  • 1
    @Dan: "I think if somebody's interested in using a class as a template parameter, that class is almost surely defining some underlying object." No, not at all. Think of traits. (Nevertheless, I fully agree with your answer.) – sbi Sep 16 '09 at 20:17
  • @Shog: never thought about the template argument. Very nice. @Martin: you can't use the namespace MyMath as a template parameter. I think that is what Shog was talking about. – D.Shawley Sep 16 '09 at 20:56
21
  • If you need static data, use static methods.
  • If they're template functions and you'd like to be able to specify a set of template parameters for all functions together then use static methods in a template class.

Otherwise, use namespaced functions.


In response to the comments: yes, static methods and static data tend to be over-used. That's why I offered only two, related scenarios where I think they can be helpful. In the OP's specific example (a set of math routines), if he wanted the ability to specify parameters - say, a core data type and output precision - that would be applied to all routines, he might do something like:

template<typename T, int decimalPlaces>
class MyMath
{
   // routines operate on datatype T, preserving at least decimalPlaces precision
};

// math routines for manufacturing calculations
typedef MyMath<double, 4> CAMMath;
// math routines for on-screen displays
typedef MyMath<float, 2> PreviewMath;

If you don't need that, then by all means use a namespace.

Shog9
  • 156,901
  • 35
  • 231
  • 235
  • 3
    so called static data can be namespace level data in the implementation file of the namespace, this reduces coupling even more since it doesn't have to show up in the header. – Motti Sep 16 '09 at 19:26
  • Static data is no better than namespace-scope globals. – coppro Sep 16 '09 at 19:27
  • @coppro. They are at least one step up the evolutionary chain from random globals as they can be made private (but otherwise agree). – Martin York Sep 16 '09 at 19:30
  • @Motti: OTOH, if you *want* it in the header (inline / template functions), you're back to being ugly about it. – Shog9 Sep 16 '09 at 19:31
  • 1
    Interesting example, using a class as a shorthand to avoid repeating `template` arguments! – underscore_d Apr 08 '16 at 13:40
  • @Motti "so called static data can be namespace level data". ***Reply***: could you please show me a simple code example? – John Sep 12 '21 at 09:15
12

You should use a namespace, because a namespace has the many advantages over a class:

  • You don't have to define everything in the same header
  • You don't need to expose all your implementation in the header
  • You can't using a class member; you can using a namespace member
  • You can't using class, though using namespace is not all that often a good idea
  • Using a class implies that there is some object to be created when there really is none

Static members are, in my opinion, very very overused. They aren't a real necessity in most cases. Static members functions are probably better off as file-scope functions, and static data members are just global objects with a better, undeserved reputation.

coppro
  • 14,338
  • 5
  • 58
  • 73
  • 4
    "You don't need to expose all your implementation in the header" neither you do when you use a class. – Vanuan Jun 22 '11 at 07:59
  • Even more: If you're using namespaces you can't expose all your implementation in the header (you'll end up with multiple definition of symbols). Inline class-member functions allow you to do that. – Vanuan Jun 22 '11 at 08:38
  • 1
    @Vanuan: You can expose namespace implementations in the header. Just use the `inline` keyword to satisfy ODR. – Thomas Eding Dec 05 '12 at 23:24
  • @ThomasEding don't need != can – Vanuan Dec 06 '12 at 02:34
  • @ThomasEding oops, ignore my previous comment. Still you can't (at least for some compilers by default): http://stackoverflow.com/questions/3763746/inline-function-in-namespace-generate-duplicate-symbols-during-link-on-gcc – Vanuan Dec 06 '12 at 03:37
  • 3
    @Vanuan: Only one thing is guaranteed by the compiler when using `inline`, and it is NOT "inlining" a function's body. The *real* (and guaranteed by the standard) purpose of the `inline` is to prevent multiple definitions. Read about "One Definition Rule" for C++. Also, the linked SO question wasn't compiling due to precompiled header issues instead of ODR issues. – Thomas Eding Dec 06 '12 at 18:33
  • Oh, if it's defined in standard, then there's probably a bug in gcc. – Vanuan Dec 07 '12 at 09:44
  • "static data members are just global objects with a better, undeserved reputation."... in many cases, I'd enthusiastically agree, except that this is an oversimplification that ignores the privileged access of `static` members to `private` elements of instances. That can be essential. Sure, many people use `static` members in this way, but that's not all they can do, and they certainly look better than using a global object and having to explicitly grant `friend` access for everything it might need. – underscore_d Apr 08 '16 at 13:42
  • One disadvantage: you cannot use the namespace as a template type as opposed to a class. – Matthias Sep 23 '17 at 11:37
5

I want to summarize and add to other answers. Also, my perspective is in the world of header-only.


Namespaces

Pros:

  • simple solution for naming hierarchies
  • they carry no semantics, so it is simpler to read
  • can live in different files (headers)
  • can be extended
  • ADL
  • shortcut can be defined (using).
  • Plays well with operator overload
  • Can be used for branding (you can design your code and put a namespace over it without much though)

Cons:

  • everything is public
  • private things need unnamed namespace so it is not explicit
  • ADL (yes, some people despise ADL)
  • can be extended (this can be a bad thing, specially in combination with ADL, semantics of existing code can change by extending the namespace)
  • functions need to be defined (or declared) in order of use

Classes with static methods

Pros:

  • can have private components (function, variables) and they are explicitly marked.
  • classes can be friended
  • can be type-parametrized (templates)
  • can be template parameters themselves
  • can be instantiated
  • can be passed to functions (static functions behave like non-static method by default).
  • it is easier to find patterns and go from groups of independent functions and convert them to a proper class (eventually with non static members)
  • dependencies among classes is well defined
  • functions (the static method) can be defined in any order

Cons:

  • No ADL
  • cannot be extended
  • needs the keyword static everywhere (opportunity to make fun of the language)
  • an overkill to solve the naming problem alone. Difficult to read in that case.
  • the functions (static methods) always need qualification (myclassspace::fun). There is no way to declare shortcuts (using).
  • almost useless for operator overload, needs complicated friend mechanism for that.
  • can not be used for branding.
  • you need to remember end it with ; :)

In summary, classes with static methods are better units of code and allow more meta programming, and except for ADL and some syntactic quirks, can replicate all the features of namespaces, but they can be an overkill sometimes.

Companies, such as Bloomberg, prefer classes over namespaces. If you don’t like ADL or operator overload, classes with static methods is the way to go.

IMO, it would be nice if namespace and classes are integrated to become two sides of the same coin. For example identify a namespace in the language as a class were the methods are static by default. And then be able to use them as template parameters. I wouldn't be sure what to do with ADL (may be it could be restricted to symbolic operators functions alone, e.g. operatorX, which was the original motivation for operator overload and ADL in the first place)

alfC
  • 14,261
  • 4
  • 67
  • 118
4

I would prefer namespaces, that way you can have private data in an anonymous namespace in the implementation file (so it doesn't have to show up in the header at all as opposed to private members). Another benefit is that by using your namespace the clients of the methods can opt out of specifying MyMath::

Motti
  • 110,860
  • 49
  • 189
  • 262
1

Why would I choose one over the other as a means of organizing my software?

If you use namespaces, you will frequently hit a language defect that functions which call each other must be listed in a specific order, because C++ can't see definitions further down in the file.

If you use classes, this defect does not occur.

It can be easier and cleaner to wrap implementation functions in a class than to maintain declarations for them all or put them in an unnatural order to make it compile.

Boann
  • 48,794
  • 16
  • 117
  • 146
0

Both namespace and class method have their uses. Namespace have the ability to be spread across files however that is a weakness if you need to enforce all related code to go in one file. As mentioned above class also allows you to create private static members in the class. You can have it in the anonymous namespace of the implementation file however it is still a bigger scope than having them inside the class.

rocd
  • 1
  • 2
  • "[storing things] in the anonymous namespace of the implementation file [is] a bigger scope than having them inside the class" - no, it is not. in cases where privileged access to members is not required, anonymously namespaced stuff is **more private** than `private:` ones. and in many cases where privileged access _seems_ to be required, that can be factored out. the most 'private' function is one that doesn't appear in a header. `private:` methods can never enjoy this benefit. – underscore_d Apr 08 '16 at 13:45
0

One more reason to use class - Option to make use of access specifiers. You can then possibly break your public static method into smaller private methods. Public method can call multiple private methods.

Milind T
  • 25
  • 1
  • 7
    The access modifiers are cool, but even the most `private` method is more accessible than a method whose prototype is not published at all in a header (and thus, remains invisible). I'm not even mentioning the better encapsulation offered by anonymously namespaced functions. – paercebal Feb 17 '12 at 18:00
  • 2
    Private methods are, IMO, inferior to hiding the function itself in the implementation (cpp file) and never exposing it in the header file. Please elaborate on this in your answer and why you would prefer to use *private* members. Until then -1. – nonsensickle Mar 30 '14 at 23:19
  • @nonsensickle Perhaps he means that a mammoth function with many repeated sections can be broken down safely while hiding the offending subsections behind private, stopping others from getting at them if they are dangerous/need very careful usage. – Troyseph Nov 13 '15 at 13:09
  • 1
    @Troyseph even so, you can hide this information inside an unnamed namespace in the `.cpp` file which would make it private to that translation unit without giving any superfluous information to anyone reading the header file. Effectively, I'm trying to advocate for the PIMPL idiom. – nonsensickle Nov 15 '15 at 04:09
  • You can't put it in a `.cpp` file if you want to use templates. – Yay295 Jul 16 '18 at 22:16