views:

244

answers:

5

I have a class that has 5 static public functions and 1 static private function (called from one of the public functions). The class doesn't have any member variables. It seems to me that it should be a namespace and not a class. But what to do with the private function? I prefer it not to be accessible by every namespace user, but there is no access control in namespaces.

+8  A: 

I don't think there is a solution to this :)

One -different- solution, would be to separate these functions into a separate compilation unit, then declare the private functions inside an anonymous namespace.

AraK
+1 An anonymous namespace in the implementation file is the way to go. Lately I've been doing this for previously non-static "private" that make sense as free functions to keep implementation details out of the header.
Adam Bowen
+4  A: 

Keep the public declaration in the header file. Move the implementations to a cpp file. Mark previously private methods as static. This will make them unaccessible from a different linker objects (compilation units) and effectively hide them.

Marcin Seredynski
no, don't mark them `static` put them in an anonymous namespace in the cpp file where it's implemented
Gregory Pakosz
And why is this the right way of achieving the desired effect?
Marcin Seredynski
@Marcin Take a look at:http://stackoverflow.com/questions/154469/unnamed-anonymous-namespaces-vs-static-functions
AraK
Fair enough. Thank you :) +1
Marcin Seredynski
+12  A: 

There are two ways i know of

Don't declare them in the header

One way is to not declare those functions inside the header. They can be placed into unnamed namespaces within the implementation file, only.

Indeed, you will then have to implement any function that accesses this private function in the implementation file (not inline in the header).

Put them into a detail namespace

Preferably, you put them in a different header, and include them. So the code of them won't disturb your interface header. This is how boost does it, too:

#include "detail/destroy.hpp"

namespace orbit {
  void destroy() {
    detail::destroy_planets();
    detail::destroy_stars();
  }
}
Johannes Schaub - litb
+1: for the boost reference -- I have a lot of "detail" code in my repos -_-
Kornel Kisielewicz
+1 I saw the second method in `boost` source code many times, but you have a better memory my friend ;)
AraK
+1. This is way more descriptive thah AraK's answer.
Marcus Lindblom
I tend to use the `detail` approach too, Alexandrescu used a `Private` nested namespace in `Loki`. I would also like to point out the better encapsulation of implementation that comes with NOT declaring the functions in the header and resorting to a different header (meaning 3 files: `thing.h`, `thingImpl.h`, `thing.cpp`)
Matthieu M.
+3  A: 

It seems to me it should be a class, not a namespace. Namespaces in C++ are primarily name resolution tools, and are not intended as the basis for design and do not really provide encapsulation. So I would leave it as it is.

anon
+1: that's a question I'd like to ask actually
Kornel Kisielewicz
Depends on how it is used, i have seen classes with static member functions used as a substitute for namespaces, say `string_util`.
Georg Fritzsche
@gf Indeed. But in this case he has a private member, which indicates to me he should use a class.
anon
@Neil, yeah i think i sort of agree with you. But imagine `string_util` has private helper functions / classes. Would you consider keeping `string_util` as a class? I think i would still make it a namespace, and put the private functions or classes into `detail`. Rough rule for me: If it has data, make it a class. If it has only functions, make it a namespace.
Johannes Schaub - litb
A: 

Another solution which, however, does not manage to get completely rid of classes, would be to keep all private functions in some class as static methods, and to have public functions in the namespace. Then allow the public functions to use the class using friend:

#include <iostream>

// forward declaration of Module::PublicFn()
namespace Module {
    void PublicFn();
};

// static class for private functions (methods)
class ModulePrivates
{
private:
    // disallow instantiation by making constructor private
    ModulePrivates() { }
private:
    // example of a private function
    static void PrivateFn()
    {
        std::cout << "ModulePrivates::PrivateFn() called." << std::endl;
    }

    // allow public function to call PrivateFn()
    friend void Module::PublicFn();
};

// namespace for public functions
namespace Module
{
    void PublicFn()
    {
        std::cout << "Module::PublicFn() called." << std::endl;
        ModulePrivates::PrivateFn();
    }
};

This is clearly only a half-way solution, since you could just as well keep everything in a class (which is what I'd suggest!). Still, you get a namespace with public functions, only there will be one additional class (which however cannot be instantiated and which looks empty from the "outside".)

stakx