Adri C.S.
Adri C.S.

Reputation: 3007

Private namespace in source files

I have a doubt regarding private methods & functions. Let's say I have some utility methods that needn't be inside a class. But those same methods need to call other ones that I don't want to expose to the user. For example:

Suspect.h

namespace Suspect {
  /**
  *  \brief This should do this and that and more funny things.
  */
  void VerbalKint(void);  // This is for you to use
}

Suspect.cpp

namespace Suspect {
  namespace Surprise {
    /**
    * \brief The user doesn't need to be aware of this, as long 
    *        the public available VerbalKint does what it should do.
    */
    void KeyserSoze(void) {
      // Whatever
    }
  } // end Surprise

  void VerbalKint(void) {
    Surprise::KeyserSoze();
  }
}

So, this layout works. When including the Suspect.h, only VerbalKint is visible. This can be as well achieved using a class and marking VerbalKint as static:

class Suspect {
public:
  // Whatever
  static void VerbalKint(void);
private:
  static void KeyserSoze(void);
};

I would like to know if there's any difference between the two approaches. Is one better (faster, easier to maintain) than the other?

What are your thoughts?

Upvotes: 30

Views: 19872

Answers (4)

justin
justin

Reputation: 104698

If the functions are 'free', you should use an anonymous namespace in the *.cpp:

namespace Suspect {
namespace Surprise {
namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon
} // end Surprise
} // end Suspect

or even:

namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon

This keeps it away from clients so they cannot access, depend on, or collide with your exports when linking. It also keeps unnecessary declarations from them, reducing their compile times and potentially link times or binary sizes if definitions are visible. Finally, it makes it private so they cannot depend on it and you do not need to maintain it for their use. You can still pass these to the outside world, if you choose (function pointer in KeyserSoze()'s case).

At other times, it is preferable to declare a private member function in your class then define it in the *.cpp (where possible). Typically, you would opt for this approach when you need a closer relationship with the class (e.g. when you need access to some members). You said this was not the case in the question, but I'm just reiterating when private members should be used.

Upvotes: 29

Tom Tanner
Tom Tanner

Reputation: 9354

The main difference between putting something in a class or a namespace is that you can't add extra static functions to a class in another header file.

This: a.h

namespace Fred {
   void Somefunc();
}

b.h

namespace Fred {
   void Anotherfunc();
}

work, although neither a nor b know what each other has done to their namespaces. This could conceivably cause problems, such as this:

c.h

namespace Fred {
   void Thirdfunc();
}

d.h

namespace Fred {
   bool Thirdfunc();
}

which is all fine and dandy until you get to run the program...

This is, whilst not impossible, a lot less likely with classes.

In your example, with only one source file, you might also want to consider using the anonymous namespace as that restricts declarations to file scope, so people outside your file can't access them (or clash with them) by accident.

Upvotes: 2

Jeff Dun
Jeff Dun

Reputation: 412

The best approach is to define all helper functions in an unnamed namespace in Suspect.cpp, instead of in the Suspect::Surprise namespace.

In your case, this would be:

namespace{
void KeyserSoze(){ ... };
}

You can simply call KeyserSoze without any namespace specifiers from within Suspect.cpp.

You can find more information about that here: Unnamed/anonymous namespaces vs. static functions

Another alternative is to declare KeyserSoze to be static, but this is not advised by the standard. The C++ Standard reads in section 7.3.1.1 Unnamed namespaces, paragraph 2:

The use of the static keyword is deprecated when declaring objects in a namespace scope, the unnamed-namespace provides a superior alternative

Upvotes: 10

Matthieu M.
Matthieu M.

Reputation: 299730

Actually, even though the function is not visible to the eye when you do not declare it in any header; it still is available to the user should they write the declaration.

In C++, the mechanism to hide symbols declared at file level is:

  • static for (global) variables and functions
  • namespace { ... } (anonymous namespaces) for anything you wish (more general, more verbose)

For example:

// Suspect.cpp

namespace Suspect {

    static void KeyserSore() {}

    void VerbalKing() { KeyserSore(); }

}

Upvotes: 6

Related Questions