Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

c++ - Namespace + functions versus static methods on a class

Let's say I have, or am going to write, a set of related functions. Let's say they're math-related. Organizationally, should I:

  1. Write these functions and put them in my MyMath namespace and refer to them via MyMath::XYZ()
  2. Create a class called MyMath and make these methods static and refer to the similarly MyMath::XYZ()

Why would I choose one over the other as a means of organizing my software?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By default, use namespaced functions.

Classes are to build objects, not to replace namespaces.

In Object Oriented code

Scott Meyers wrote a whole Item for his Effective C++ book on this topic, "Prefer non-member non-friend functions to member functions". I found an online reference to this principle in an article from Herb Sutter: http://www.gotw.ca/gotw/084.htm

The important thing to know is that: In C++, functions that are in the same namespace as a class is, and that have that class as a parameter, belong to that class' interface (because ADL will search those functions when resolving function calls).

For example:

  • let's say you have a namespace N
  • let's say you have a class C, declared in namespace N (in other words, its full name is N::C)
  • let's say you have a function F, declared in namespace N (in other words, its full name is N::F)
  • let's say that function F has, among its parameters, a parameter of type C

... Then N::F is part of N::C's public interface.

Namespaced functions, unless declared "friend," have no access to the class' internals, whereas static methods have.

This means, for example, that when maintaining your class, if you need to change your class' internals, you will need to search for side effects in all its methods, including the static ones.

Extension I

Adding code to a class' interface.

In C#, you can add methods to a class even if you have no access to it. But in C++, this is impossible.

But, still in C++, you can still add a namespaced function, even to a class someone wrote for you.

See from the other side, this is important when designing your code, because by putting your functions in a namespace, you will authorize your users to increase/complete the class' interface.

Extension II

A side-effect of the previous point, it is impossible to declare static methods in multiple headers. Every method must be declared in the same class.

For namespaces, functions from the same namespace can be declared in multiple headers (the almost-standard swap function is the best example of that).

Extension III

The basic coolness of a namespace is that in some code, you can avoid mentioning it, if you use the keyword using:

#include <string>
#include <vector>

// Etc.
{
   using namespace std ;
   // Now, everything from std is accessible without qualification
   string s ; // Ok
   vector v ; // Ok
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

And you can even limit the "pollution" to one class:

#include <string>
#include <vector>

{
   using std::string ;
   string s ; // Ok
   vector v ; // COMPILATION ERROR
}

string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR

This "pattern" is mandatory for the proper use of the almost-standard swap idiom.

And this is impossible to do with static methods in classes.

So, C++ namespaces have their own semantics.

But it goes further, as you can combine namespaces in a way similar to inheritance.

For example, if you have a namespace A with a function AAA, a namespace B with a function BBB, you can declare a namespace C, and bring AAA and BBB in this namespace with the keyword using.

You can even bring the full content of a namespace inside another, with using namespace, as shown with namespace D!

namespace A
{
   void AAA();
   void AAA2();
}

namespace B
{
   void BBB();
}

namespace C
{
   using A::AAA;
   using B::BBB;
}

namespace D
{
   using namespace A;
   using namespace B;
}

void foo()
{
   C::AAA();
   // C::AAA2(); // ERROR, won't compile
   C::BBB();
}

void bar()
{
   D::AAA();
   D::AAA2();
   D::BBB();
}

Conclusion

Namespaces are for namespaces. Classes are for classes.

C++ was designed so each concept is different, and is used differently, in different cases, as a solution to different problems.

Don't use classes when you need namespaces.

And in your case, you need namespaces.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...