Allow C++ class to access some "internal" member of other class, but not private?
When coding classes that are tightly coupled functionally, but where you want a simple interface to the rest of the world, it would be neat if I could do something like this:
class log
{
private:
log_context& cont;
public:
create_log_section(std::string name)
{
cont.create_log_section(name);// this is fine! It's "internal"
cont.this_is_private(); // doesn't compile. Don't want anyone touching my privates!
}
};
class log_context
{
internal:
void create_log_section(std::string name);
private:
void this_is_private();
internal friend log; // Wow, possible?
}
Now, this would allow log to access the relevant parts of context, but not the private ones. The rest of the program should use log to add any context. It could also pass around strongly typed log_contexts开发者_C百科
between logs without having any extra power. I realize that this particular solution is not possible, but what are some common ones, if any?
You can use an internal class to do so
class log_context
{
class internal
{
friend log;
static void create_log_section( log_context & context, std::string name)
{
context.create_log_section( name );
}
}
private:
void create_log_section(std::string name);
void this_is_private();
}
class log
{
private:
log_context& cont;
public:
void create_log_section(std::string name)
{
log_context::internal::create_log_section( cont, name );// this is fine! It's "internal"
}
};
As internal as only private static functions, only its friends can access it
Friendships don't cross inheritance boundaries. If log_context
was to inherit some log_context_base
, and this_is_private
were to be part of log_context_base
, then log_context
being a friend of log
would not have allowed log
to access this_is_private
.
class log_context_base
{
protected:
void this_is_private();
}
class log_context : protected log_context_base
{
internal:
void create_log_section(std::string name);
friend log;
}
Note that I've used protected inheritance here because I don't expect log_context to be accessed using a log_context_base*
.
This way, you'll get what you want without having to add a new keyword to the language ;)
The general solution is to make a full
friend and, since it's under your control, just make sure it only touches what it's supposed to touch.
Another solution I presented some while ago is to you use a Key
.
class Key { friend class log; Key() {} ~Key() };
class log_context {
public:
void create_log_section(std::string name, Key const&);
};
Only the friend of Key can create an instance of it, and thus only them (or those they pass a reference to the key to) can access the "restricted" method.
I'm rather fan of this method to document the limited access.
精彩评论