Static, nonmember or static nonmember function?

烂漫一生 提交于 2019-12-03 08:04:17

The difference between options 2 and 3 is that in the second case, the function will be internal to the translation unit. If the function is only defined in the cpp this should be the option (which is roughly equivalent to an unnamed namespace --which is a fourth option to consider, again roughly equivalent to 3).

If the function is to be used by different translation units then you should go with option 2. The function will be compiled once (unless you mark it as inline and provide the definition in the header), while with option 3 the compiler will create it's an internal copy in each translation unit.

As of option 1, I would avoid it. In Java or C# you are forced to use classes everywhere, and you end up with utility classes when operations do not nicely map to the object paradigm. In C++ on the other hand, you can provide those operations as free standing functions, and there is no need to add the extra layer. If you opt for the utility class, don't forget to disable the creation of the objects.

Whether the functions are at class or namespace level will affect the lookup, and that will impact on user code. Static member functions need to be qualified with the class name always, unless you are inside the class scope, while there are different ways of bringing namespace functions into scope. As an illustrative example, consider a bunch of math helper functions, and calling code:

double do_maths( double x ) {
   using namespace math;
   return my_sqrt( x ) * cube_root(x);
}
// alternatively with an utility class:
double do_maths( double x ) {
   return math::my_sqrt(x) * math::cube_root(x);
}

Which one you find easier to read is a different story, but I prefer the former: within the function I can select the namespace and then just focus on the operations and ignore lookup issues.

Don't use classes as namespaces. Using a free (ie. nonmember) function inside a namespace is the simplest thing.

Moreover, the function shouldn't be static if it has to be used across multiple translation units. Otherwise, it will be duplicated.

Using classes as namespace is stupid: why make a class which you won't instantiate ?

If some state is to be kept, then have a global state somewhere: static variable inside the function, utility global object (possibly in a "private" namespace, or as a static global variable in one of your translation units). Don't write classes you don't instantiate.

Alas, people with a C#/Java background are used to do this stupid thing, but it is because their language designers have decided unilaterally that free functions are evil. Whether they should be shot or not is a matter of religion.

As a last word of caution: global state should be rarely used. Indeed, it couples your code to the existence of the global state in a way you don't control when the code grows. You should always ask yourself why you don't make this coupling explicit.

I use struct with static functions, because it offers a slighly better isolation than non-member functions in namespaces (due to the avoidance of Koenig lookup).

To give an example of the thing I want to avoid:

namespace Foo
{
      struct A
      {
      };

      void f(const A& a) {}
}

void f(const Foo:A& a) { std::cout << "AAA"; }

int main(void)
{
      Foo::A a;
      f(a); // calls Foo:f
      return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!