Reputation: 4266
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:
MyMath
namespace and refer to them via MyMath::XYZ()
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?
Upvotes: 371
Views: 100766
Reputation: 334
If you are building a header only library, you wont have an implementation so anonymous namespaces dont work. In such a case you might want to define a class which exposes a static public function and you make your logic which you dont want to be exposed private. I.e.
namespace mylib {
class utils {
static int bar() { return 42; }
public:
static int foo() {
return bar();
}
}
}
Upvotes: 0
Reputation: 83309
By default, use namespaced functions.
Classes are to build objects, not to replace namespaces.
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.
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.
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).
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();
}
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.
Upvotes: 295
Reputation: 50020
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.
Upvotes: 2
Reputation: 16242
I want to summarize and add to other answers. Also, my perspective is in the world of header-only.
Pros:
using
).Cons:
Pros:
Cons:
myclassspace::fun
). There is no way to declare shortcuts (using
).;
:)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)
Upvotes: 7
Reputation: 1
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.
Upvotes: 0
Reputation: 35
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.
Upvotes: 1
Reputation: 159590
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.
Upvotes: 21
Reputation: 14506
You should use a namespace, because a namespace has the many advantages over a class:
using
a class member; you can using
a namespace memberusing class
, though using namespace
is not all that often a good ideaStatic 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.
Upvotes: 12
Reputation: 114695
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::
Upvotes: 4
Reputation: 128317
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).
Upvotes: 65