Inner classes and friend

P

Philip Potter

I have a graph data structure. It goes something like this:

class GraphNode {
private:
friend class Graph;
// successor GraphNodes stored as indices of the Graph's array
int value;
int next1, next2;
};

class Graph {
private:
std::vector<GraphNode> nodes;
class cmp_val {
public:
operator()(const GraphNode &l, const GraphNode &r) {
return (l.value > r.value) - (l.value < r.value);
}
};
int find_node(int val);
};

Here, Graph::cmp_val is a function object used by Graph::find_node in order
to find a node with a given value in the nodes vector. However, although
Graph is a friend of GraphNode, Graph::cmp_val doesn't inherit this
friendship, so its operator()() function cannot access l.value and r.value.

Why don't inner classes inherit their outer classes' friendships?

Is there a good reason I shouldn't just add "friend Graph::cmp_val;" to
GraphNode as well? It seems somehow wrong to me, but I can't say why.
 
J

John Carson

Philip Potter said:
I have a graph data structure. It goes something like this:

class GraphNode {
private:
friend class Graph;
// successor GraphNodes stored as indices of the Graph's array
int value;
int next1, next2;
};

class Graph {
private:
std::vector<GraphNode> nodes;
class cmp_val {
public:
operator()(const GraphNode &l, const GraphNode &r) {
return (l.value > r.value) - (l.value < r.value);
}
};
int find_node(int val);
};

Here, Graph::cmp_val is a function object used by Graph::find_node in
order to find a node with a given value in the nodes vector. However,
although Graph is a friend of GraphNode, Graph::cmp_val doesn't
inherit this friendship, so its operator()() function cannot access
l.value and r.value.

Why don't inner classes inherit their outer classes' friendships?

Probably the same reason derived classes don't inherit their base classes'
friendship. Good design says that friendship should be minimised, so you
have to make it explicit.
Is there a good reason I shouldn't just add "friend Graph::cmp_val;"
to GraphNode as well? It seems somehow wrong to me, but I can't say
why.

With very simple classes, it probably makes no difference either way. You
could define a member function of Graph that cmp_val calls to give cmp_val
the access it needs --- or you could do the same in GraphNode.
 
X

xiaohuamao

The statement "friend class Graph;" in class GraphNode means Graph is
the fried of GraphNode, that it can access the private data in Graph.
To let the inner class cmp_val to access the data of GraphNode, you
should declare GraphNode as Graph's friend.
Remove the statement "friend class Graph" from class GraphNode, but
add "friend class GraphNode " in class Graph.
 
P

Philip Potter

xiaohuamao said:
The statement "friend class Graph;" in class GraphNode means Graph is
the fried of GraphNode, that it can access the private data in Graph.

Er... no. The reason this isn't true is that there would be no point in me
declaring my data private: because anybody could get at the guts of my class
by making mine a friend of thiers.

Philip
 
P

Philip Potter

John Carson said:
Probably the same reason derived classes don't inherit their base classes'
friendship.

(That's a subtly different issue. If derived classes inherited friendships,
it would break encapsulation; this isn't the case with inner classes.)
Good design says that friendship should be minimised, so you
have to make it explicit.

Yes, I can see your point here. If the GraphNode here was an inner class of
Graph, it wouldn't make sense for GraphNode to see all of Graph's mucky
internal bits, because GraphNode is just a tool to be used exclusively by
Graph.

However, it *does* make sense for function-style classes to inherit
friendship in the same way that real functions do, and to do so without
having to change the friend-ing class. It all seems a bit inelegant, as if
there's a better way of doing things. (But I suppose that whenever a class
friends another class, it implies some sort of cosy relationship between the
two, and so adding extra friend declarations for inner classes is probably
perfectly alright.)
 
J

John Carson

Philip Potter said:
(That's a subtly different issue. If derived classes inherited
friendships, it would break encapsulation; this isn't the case with
inner classes.)

Good point. There is a difference there.
Yes, I can see your point here. If the GraphNode here was an inner
class of Graph, it wouldn't make sense for GraphNode to see all of
Graph's mucky internal bits, because GraphNode is just a tool to be
used exclusively by Graph.

However, it *does* make sense for function-style classes to inherit
friendship in the same way that real functions do, and to do so
without having to change the friend-ing class.

Yes, but there is no clear division between function-style classes and other
classes. A class that defines operator() may do all sorts of other things.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top