views:

168

answers:

5

Hi,

The title says it all. But I don't know if I should go for static methods, just a header, a class, or something else?

What would be best practice? But, I don't want to have an instance of a utility class.

I want to add functions like:

Uint32 MapRGB (int r, int g, int b);
const char* CopyString(const char* char);
// etc. You know: utility methods...
+9  A: 

Don't put them in a class; just make them non-member functions at namespace scope.

There's no rule that says every function has to be a member function of some class.

James McNellis
@James: Oh, a namespace. Maybe not bad... Can you give a little code example?
Martijn Courteaux
Some shops prefer classes over namespaces because it's more 'java like'. *sigh*
Jeff Paquette
@Martijn: I'd recommend getting one of the introductory books listed in [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Effectively, the code can be just as you show in your question, and if you want to you want or need to you can place the functions into a namespace.
James McNellis
@flyfish Anyone trying to turn C++ into Java is looking at an ocean of pain.
anon
I know syntax, but what about files? Do I have to create a separate file for it? With which name?
Martijn Courteaux
@Martijn: That's up to you. I'd recommend separating utilities and algorithms into different headers based on their use case and general functionality.
James McNellis
You can create one file per function, or one file per family of functions etc... It's a question of dependencies management and it is up to you to define the granularity you wish. It's a tradeoff since greater granularity means higher number of files but less dependencies.
Matthieu M.
If you create one file per function, be prepared to be hated by generations yet to come.
anon
@James: Thank you very much!
Martijn Courteaux
@James: Does the header for the namespace have to have header guards?
Martijn Courteaux
@James: Using a namespace has one big disadvantage if you need helper functions that should be only accessed by the utility functions but not directly not by the user. In a class you make those simply private...
rstevens
@rstevens: In that case, the helper functions may be placed in a "detail" namespace. This is, for example, what most of the Boost libraries do.
James McNellis
@James: But they are still acessible by the user...no protection like if they were private methods!
rstevens
@rstevens: That is only a problem if the user is either (a) malicious, or (b) dumb. That said, what does it matter? Non-member functions aren't member functions, so they can't improperly manipulate private state of any object; if someone wants to call them as utilities, there shouldn't be any issue.
James McNellis
@James: There may be internal utility functions that modify a class instance given as a parameter in a wrong way if the other parameters are not set properly. So you may want to prevent the user from calling them directly. This is the same reason why there private methods only used for submitted parameters.
rstevens
+1  A: 

There's probably no reason to have a class to wrap these functions if they don't logically belong to a class. In that case you can just have them be free functions. It might be appropriate to contain them in a namespace to help avoid name collisions.

If you want to provide a stringer logical grouping of the classes, there's no real harm in having them be static member functions of a class - but I see no reason why you'd have functions like MapRGB() and CopyString() need to be members of the same class.

Michael Burr
+1  A: 

One factor is whether to even put them in a class, or just put them as nomembers in a namespace (in Java, you'd have to use a class, but C++ offers namespaces).

If you do make it a class member, then the most important decision you have to make about each function is whether it would require or should affect any state that is not received or passed via a its parameters and return value. If it does not, then it should be made static, since you will not use the "this" hidden argument.

One argument for using a class instead of a namespace is if your utility class may need to invoke additional methods for its implementation (e.g., in a case of recursion, complex calculations, etc.). You could then make your method static public, and anything it is implemented over static private. It's been many years since I used C++, but I don't think you can "hide" non-member functions in a namespace (someone correct me if I'm wrong).

In terms of designing the function interface, consider the number of arguments. If there are too many incoming arguments (especially if they are of similar types and some are related), you may want to consider using additional types instead of passing multiple args. For example, instead of calculateVolume(int x, int y, int z), you may want to do something like calculateVolume(Point3D). Similarly, in your case, use an RGB class. It may seem silly, but it can save some annoying errors (e.g., if you have functions that take ints and RGBs), and time (if you have to pass the values to other functions). You can create a static factory method to make these types easier to create when passing arguments. For example: doSomethingWithColor(RGB.create(20,30,40))

Uri
+1 - For pointing out static good answer!
JonH
If a non-member function is implemented in a .cpp file, then any functions it needs but which should not be exposed can be placed into an unnamed namespace in that .cpp file (or made static). It's trickier if you have function templates, since their implementation must be in the header file itself, but generally this is worked around by having a "detail" namespace in which the non-public functionality goes. This is the approach that much of Boost takes.
James McNellis
@James: Thanks James...
Uri
A: 

If you just want to group functions together, but not create an instance of the group, then you should probably be thinking of putting them into a namespace rather than a class at all.

I would try to use meaningful namespaces though -- putting MapRGB and CopySstring together makes very little sense. If you really need both, and really don't have any other functions that deal with strings or RGB mapping, putting them into a "utillity" namespace might make sense, but if you're using those, it seems like that you have some more string "stuff" and some more "color" stuff, and could probably benefit from having a namespace for each.

Jerry Coffin
A: 

I generally have a .a (.lib on windows) called "util" that gets linked in. However, usually a "util" class is bad news, and it introduces a dependency that breaks standard object-oriented design. Now, if you try to pull out a class to reuse in a different project, you have thousands of hidden dependencies on your util library. Basically, it's useful, but do your very best to avoid putting things in there.

Clark Gaebel