Reputation: 3007
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
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
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
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
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 functionsnamespace { ... }
(anonymous namespaces) for anything you wish (more general, more verbose)For example:
// Suspect.cpp
namespace Suspect {
static void KeyserSore() {}
void VerbalKing() { KeyserSore(); }
}
Upvotes: 6