6

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...
TylerH
  • 20,799
  • 66
  • 75
  • 101
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 2
    CopyString() looks suspicious - what will it do? –  Jun 18 '10 at 15:15
  • @Neil: Copying a string to the heap, so it won't get out of scope... – Martijn Courteaux Jun 18 '10 at 15:16
  • 9
    Do not, under any circumstances do that - it's an almost guaranteed memory leak. Use std::string. –  Jun 18 '10 at 15:18
  • @Neil: But std::string will also go out of scope, when it is created on the stack? – Martijn Courteaux Jun 18 '10 at 15:21
  • 1
    @Martijn: When you return a string by value, it is copied on return. You should get one of the introductory books listed on [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Those books contain very good explanations of the basic workings of C++. – James McNellis Jun 18 '10 at 15:24
  • 3
    I second James here - from your questions, you seem to really need a good book on C++ programming and design. You cannot learn C++ from asking questions on SO. –  Jun 18 '10 at 15:26
  • @Neil @James: Indeed! Now I remember, it is passed by value. The copy constructor will be called. – Martijn Courteaux Jun 18 '10 at 15:28
  • On most implementations there isn't even copied much when "copying" a std::string by value since it uses an optimization by referencing the old value and create a copy only if the string is to be modified. – mmmmmmmm Jun 18 '10 at 16:54

5 Answers5

27

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
  • 348,265
  • 75
  • 913
  • 977
  • @James: Oh, a namespace. Maybe not bad... Can you give a little code example? – Martijn Courteaux Jun 18 '10 at 15:12
  • Some shops prefer classes over namespaces because it's more 'java like'. *sigh* – Jeff Paquette Jun 18 '10 at 15:12
  • 3
    @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 Jun 18 '10 at 15:13
  • 12
    @flyfish Anyone trying to turn C++ into Java is looking at an ocean of pain. –  Jun 18 '10 at 15:14
  • I know syntax, but what about files? Do I have to create a separate file for it? With which name? – Martijn Courteaux Jun 18 '10 at 15:15
  • @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 Jun 18 '10 at 15:18
  • 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. Jun 18 '10 at 15:18
  • 7
    If you create one file per function, be prepared to be hated by generations yet to come. –  Jun 18 '10 at 15:20
  • @James: Does the header for the namespace have to have header guards? – Martijn Courteaux Jun 18 '10 at 16:10
  • 1
    @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... – mmmmmmmm Jun 18 '10 at 16:56
  • 1
    @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 Jun 18 '10 at 17:18
  • @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 Jun 19 '10 at 13:29
  • @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. – mmmmmmmm Jun 19 '10 at 14:33
3

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
  • 88,451
  • 51
  • 221
  • 321
  • 2
    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 Jun 18 '10 at 15:23
1

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
  • 333,147
  • 50
  • 533
  • 760
1

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
  • 476,176
  • 80
  • 629
  • 1,111
1

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
  • 17,280
  • 20
  • 66
  • 93