1

I want to write a utility in my program which can convert a string to int. I know that I could use atoi or strtol for it but I need some error handling on it. Which is the better way to do it? Should I create a simple global function, maybe only in a specific namespace, or create a class that have a member which can do it for me?

For eg.:

    namespace utility{

        int ConvertStrToInt(std::string* str, int& convertednum)
        {
          //do the conversion and error handling
        return convertednum;
        }
    }

or

    class Utility{
    public:
        static int ConvertStrToInt(std::string* str, int& convertednum)
        {//do the conversion and error handling here} 
    }

Sorry if the question sounds a bit silly but I am in a team with 2 other guy and we think about this very differently. 1 says the class is for everything and make classes for everything, and I think that for such a simple problem a simple function is a good solution.

So which is the more efficient? When should I use a simple function and when is the point from where class is the good solution?

Thx for everyone!

bapszy
  • 13
  • 3
  • 4
    Do your colleagues have a Java background? In C++ there is absolutely no need for everything to be a class. – juanchopanza Aug 08 '12 at 08:09
  • There are already functions to do this. See e.g. [`strtol`](http://en.cppreference.com/w/cpp/string/byte/strtol) or [`std::stoi`](http://en.cppreference.com/w/cpp/string/basic_string/stol). – Some programmer dude Aug 08 '12 at 08:09
  • Did you mean to have `static int ConvertStrToInt` inside Utility? – Roman Saveljev Aug 08 '12 at 08:13
  • Do your colleagues have a C# background? In C++ there is absolutely no need for everything to be a class. – Sebastian Mach Aug 08 '12 at 09:19
  • Of course it should be static in Utility. He has JAVA background, and we are all junior programers, from different universities, and different knowlage levels. – bapszy Aug 08 '12 at 09:23

5 Answers5

5

The class Utility as you have written it down above somehow contradicts the idea behind object oriented programming, as the method neither uses nor depends on any members of the class. Classes should rather be objects that have certain properties and methods on these properties.

Jakob S.
  • 1,851
  • 2
  • 14
  • 29
2

If it is useful to have state in your conversion, use a class. Preferably, a functor so you can pass an instance around as a callable entity. If there is no state, then use a function.

As an aside, your signature and return type should probably look like this:

int ConvertStrToInt(const std::string& str);

Edit concerning this particular example, the C++ standard library provides this functionality already, so you don't need to re-implement it.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • what do you think about exactly? I know only strol, atoi and stringtream to do that conversion, but atoi is unsafe for eg. – bapszy Aug 08 '12 at 08:53
  • @bapszy I was thinking of `stringstream` or C++11 [stoi and related functions](http://en.cppreference.com/w/cpp/string/basic_string/stol). There's also `boost::lexical_cast`, outside of the standard library. – juanchopanza Aug 08 '12 at 10:25
1

namespace is the usual way to go about this.

The function in the class should be declared static anyway, and having a class just so you can group functions together isn't good practice.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

Neither. Go for a function object (sometimes called a Functor).

struct str_to_int {
  int operator()(const std::string& s) const { return 23; }
};

Why? This gives you the ability to add state if you need it. It works with all standard algorithm facilities and every modern C++ library. You can make it a template function without your users every noticing it.

Now you can do things like:

std::vector<std::string> strings;
std::vector<int> integers;
std::transform(begin(strings), end(strings), 
               std::back_inserter(integers), str_to_int());

Or someday turn your definition into:

struct str_to_int {
  int operator()(const std::string& s) const { return 23; }
  // ha
  int operator()(const std::wstring& s) const { return 42; }
  // haha!
  int operator()(const char* x) const { return 42; }
};

and the above code will continue to work without a problem. This wont be the case for a free function.

Random Remark: Why would you pass a pointer to a string for something like that?

Community
  • 1
  • 1
pmr
  • 58,701
  • 10
  • 113
  • 156
  • 1
    So, do you not write free functions at all, and only use function objects? Because I can't see how your argument of *"This gives you the ability to add state if you need it"* wouldn't apply to absolutely everything. – Benjamin Lindley Aug 08 '12 at 08:06
  • @BenjaminLindley It is mostly in terms to prevent breaking compatibility. The same goes for overloads. I added an example to make that clearer. If I have spec'd something so thoroughly that I know it will never ever need to be a functor, I'd go for the free-function. – pmr Aug 08 '12 at 08:09
  • The only reason to prefer a functional object to a normal function here is performance; it's easier for the compiler to inline if you use a functional object. (State might also be an issue in some cases, but not here. And given that the STL copies the the functional objects, mutable state can be tricky.) – James Kanze Aug 08 '12 at 09:15
  • @JamesKanze I didn't want to go into performance, because some people will argue that the compiler can always inline (Same goes for `std::mem_fun`). Mutable state can be dealt with through `std::ref` and I think the overload example makes a very compelling use case. `static_castS` for function disambiguation are so ugly that I consider them unusable. – pmr Aug 08 '12 at 12:56
  • @pmr I more or less agree with regards to performance. The extra (indirect) function call is probably not measurable compared to the conversion his function does. (It could make a difference in other cases.) And there's no need for function disambiguation if you don't overload the function to begin with. – James Kanze Aug 08 '12 at 13:08
0

I would normally just use a function. Putting it into a class is just noise (or pseudo-OO, since the class doesn't have any real behavior on its own).

There is one exception: functional template arguments to the STL are generally more efficient if you use a class with an operator()(), rather than a function. (If you use a functional object, the actual function being called is a compile time constant, and can easily be inlined. If you use a function, the template argument is the type of the function, not the function itself, and inlining is less likely.) Even in this case, however, I'd start with the function, and add the functional object type if needed.

James Kanze
  • 150,581
  • 18
  • 184
  • 329