58

I am working on a C++ project where I have a bunch of math functions that I initially wrote to use as part of a class. As I've been writing more code, though, I've realized I need these math functions everywhere.

Where is the best place to put them? Let's say I have this:

class A{
    public:
        int math_function1(int);
        ...
}

And when I write another class, I can't (or at leat I don't know how to) use that math_function1 in that other class. Plus, I've realized some of this functions are not truly related to class A. They seemed to be at the beginning, but now I can see how they're just math functions.

What is good practice in this situation? Right now I've been copy-pasting them into the new classes, which I'm sure is the worst practice.

4
  • 11
    Have you learned about the static keyword?
    – S.Lott
    Commented Feb 10, 2012 at 18:36
  • 33
    In C++, free functions are almost always preferred over member functions.
    – Pubby
    Commented Feb 10, 2012 at 18:54
  • 4
    There is no rule that says everything has to be in a class. At least not in C++.
    – tdammers
    Commented Feb 11, 2012 at 9:58
  • 2
    I'd prefer a namespace to a class with a bunch of static methods Commented May 25, 2017 at 10:54

5 Answers 5

85

C++ can have non-method functions just fine, if they do not belong to a class don't put them in a class, just put them at global or other namespace scope

namespace special_math_functions //optional
{
    int math_function1(int arg)
    {
         //definition 
    }
}
5
  • 7
    +1 This is the most sensible solution, although the extra namespace doesn't seem necessary.
    – Pubby
    Commented Feb 10, 2012 at 18:51
  • 1
    no it isn't necessary
    – jk.
    Commented Feb 10, 2012 at 18:55
  • 36
    Some namespace is useful to reduce potential name collisions with other libraries.
    – Bill Door
    Commented Feb 10, 2012 at 21:13
  • 13
    Using a namespace is also nice because it disambiguates whether the call is a method or a function. (math_function1(42) might call a member of the current class; special_math_functions::math_function1(42) is clearly calling an independent function). That being said, ::math_function(42) provides the same disambiguation.
    – ipeet
    Commented Feb 10, 2012 at 21:51
  • 2
    Namespaces aren't necessary but they're not prohibited either. Hence why this answer says // optional. Season according to taste. Commented May 7, 2018 at 22:42
11

Depends on how the project is organized and what sort of design patterns you are using, assuming this is strictly utility code you have the following options:

  • If you don't have to use objects for everything you could do something simple like just putting them all in a file without a class wrapper around them. This could be with or without a namespace although the namespace is recommended to prevent any issues in the future.
  • For managed C++ you can create a static class to contain them all; however, this doesn't really work the same as an actual class and my understanding is that it is a C++ anti-pattern.
  • If you aren't using managed C++ then you can just make use of static functions to allow you to access them and have them all contained in a single class. This may be useful if there are also other functions that you would want a proper instantiated object for by may also be an anti-pattern.
  • If you want to ensure that only one instance of the object containing the functions will exist then you can use the Singleton Pattern for a utility class which also allows you some flexibility in the future as you now have access to non-static attributes. This is going to be of limited use and only really applies if you need an object for some reason. Odds are if you do this you will already know why.

Note that the first option is going to be the best bet and the following three are of limited usefulness. That said though, you might encounter then just due to C# or Java programmers doing some C++ work or if you ever work on C# or Java code where the use of classes is mandatory.

9
  • Why the down-vote?
    – rjzii
    Commented Feb 10, 2012 at 20:04
  • 13
    I'm not the downvoter, but probably because you are advising a class with static functions or a singleton, while free functions would probably be fine in this case (and are acceptable and useful for many things in C++).
    – Komi Golov
    Commented Feb 10, 2012 at 21:00
  • @AntonGolov - Free functions are the first thing that I mentioned in the list. :) The rest of them are the more OOP oriented approaches for situations where you are dealing with "Everything must be a class!" environments.
    – rjzii
    Commented Feb 10, 2012 at 21:09
  • 11
    @Rob Z: However, C++ is not one of those "Everything must be a class!" environments. Commented Feb 10, 2012 at 21:12
  • 2
    Since when is it OOP to force pure functions into a class? Seems more like OOP-cargo-cult. Commented Feb 14, 2015 at 16:49
1

As you already said, copy-pasting the code is the worst form of code reuse. If you have functions that don't belong to any of your classes or may be used in for several scenarios, the best place to put them would a helper or utility class. If they don't use any instance data, they can be made static, so you don't need to create an instance of the utility class to use it.

See here for a discussion of static member functions in native C++ and here for static classes in managed C++. You could then use this utility class wherever you would have pasted your code.

In .NET for instance, things like Min() and Max() are provided as static members on the System.Math class.

If all your functions are math-related and you would otherwiese have a gigantic Math class, you might want to break it down further and have classes like TrigonometryUtilities, EucledianGeometryUtilities and so on.

Another option would be to put shared functionality into a base class of the classes requiring said functionality. This works well, when the functions in questions need to operate on instance data, however, this approach is also less flexible if you want to avoid multiple inheritance and only stick to one base class, because you would be "using up" your one base class just to get access to some shared functionality.

3
  • 21
    IMHO, utility classes with nothing but static members are an anti-pattern in C++. You're using a class to perfectly reproduce the behaviour of a namespace, which really makes no sense.
    – ipeet
    Commented Feb 10, 2012 at 21:46
  • +1 for mentioning utility classes. Languages like C# require everything to be in a class so it's quite common to create a number of utility classes for various purposes. Implementing these classes as Static make the utilities even more user friendly and avoids the headaches that inheritance can sometimes create, particularly when the base classes are becoming bloated with code that may only be used by one or two descendants. Similar techniques can be applied in other languages to provide a meaningful context for your utility functions, rather than leaving them floating in the global scope.
    – S.Robins
    Commented Feb 10, 2012 at 21:51
  • 7
    @S.Robins: There's no need for anything like that in C++, you can just put them in a namespace, which has the exact same effect.
    – DeadMG
    Commented Feb 11, 2012 at 14:26
0

Disambiguate the term "Helper function". One definition is a convenience function that you use all the time just to get some job done. Those can live in the main namespace and have their own headers, etc. The other helper function definition is a utility function for a single class or class family.

// a general helper 
template <class T>
bool isPrinter(T& p){
   return (dynamic_cast<Printer>(p))? true: false;
}

    // specific helper for printers
namespace printer_utils {    
  namespace HP {
     print_alignment_page() { printAlignPage();}
  }

  namespace Xerox {
     print_alignment_page() { Alignment_Page_Print();}
  }

  namespace Canon {
     print_alignment_page() { AlignPage();}
  }

   namespace Kyocera {
     print_alignment_page() { Align(137,4);}
   }

   namespace Panasonic {
      print_alignment_page() { exec(0xFF03); }
   }
} //namespace

Now isPrinter is available to any code including its header, but print_alignment_page requires a using namespace printer_utils::Xerox; directive. One may also reference it as

Canon::print_alignment_page();

to be more clear.

The C++ STL has the std:: namespace which covers almost all of its classes and functions, but it breaks them up categorically into over 17 different headers to allow the coder to get the class names, function names, etc out of the way if they want to write their own.

In fact, it is NOT recommended to use using namespace std; in a header file or, as is often done, as the first line inside main(). std:: is 5 letters and often seems a chore to preface the function one wants to use (especially std::cout and std::endl !) but it does serve a purpose.

The new C++11 has some sub-namespaces in it for special services such as

std::placeholders,
std::string_literals,
std::chrono,
std::this_thread,
std::regex_constants

that can be brought in for use.

A useful technique is namespace composition. One defines a custom namespace to hold the namespaces you need for your particular .cpp file and use that instead of a bunch of using statements for each thing in a namespace you might need.

#include <iostream>
#include <string>
#include <vector>

namespace Needed {
  using std::vector;
  using std::string;
  using std::cout;
  using std::endl;
}

int main(int argc, char* argv[])
{
  /*  using namespace std; */
      // would avoid all these individual using clauses,
      // but this way only these are included in the global
      // namespace.

 using namespace Needed;  // pulls in the composition

 vector<string> str_vec;

 string s("Now I have the namespace(s) I need,");

 string t("But not the ones I don't.");

 str_vec.push_back(s);
 str_vec.push_back(t);

 cout << s << "\n" << t << endl;
 // ...

This technique limits exposure to the whole std:: namespace (it's big!) and allows one to write cleaner code for the most common code lines that people write the most often.

-2

You might want to put it in a template function as to make it available for different types of integers and/or floats:

template <typename T>
T math_function1(T){
 ..
}

You could than also create neat custom types that represent for example huge numbers or complex numbers by overloading relevant operators for your custom type to make them template friendly.

Not the answer you're looking for? Browse other questions tagged or ask your own question.