C++ class design questions
I have a class Node. This class can add or remove other nodes relative to itself. Node is used by a List class. To prevent the nodes being modified directly (externally, IE not by the appropriate classes) during usage and causing problems with the List class, the nodes add/remove functions are either protected or private. This requires that List class is a friend to Node.
However, the problem with this is that the List class itself is a template class for other subclasses, and adding prototyping/adding the friend keyword for each subclass is clearly not the best solution.
How would I design the Node and List class/subclasses so that:
- Node cannot be constructed by itself externally, is only constructed with specific classes/subclasses?
- Node can construct/remove other nodes given above?
- Node functions are only accessible to specific classes (List, list subclasses, and list helper classes - list helper classes are not subclasses of list)?
- The node variable (Item) is publicly accessible give above?
- List, list subclasses and list helper开发者_C百科 classes can directly modify or indirectly modify the non-public variables of Node?
Are these possible, and if so, how?
The standard library’s std::list
class template is an example of how to design a list class so that no access to the internal nodes etc. is given to the client code.
With no access, no undesired meddling…
However, in general, it's more practical to trust a little, to not take it upon your shoulders to ensure that others’ code will be correct. It is a lot of work to express all the usage restrictions in C++. Opening up just a little can save a lot of work – so it’s a trade-off.
Cheers & hth.,
I would make Node
a protected nested class of List
:
class List
{
...
protected:
class Node
{
...
};
};
This way, only List and its subclasses can access it. Since it is nested within It also helps to highlight the functional relationship between the two classes. This probably takes care of all your dot points except the third.List
, list may access its private/protected members and functions.
EDIT double checking my facts, it seems that in C++ enclosing classes do not have special access permissions to nested class members after all (seems that's a Java thing), see here. As such, you will need to make Node
members public, but I still think this solution encourages good encapsulation.
I am not sure that I understand the problem in question, so instead of providing an answer I will provide with different approaches:
Have
list
be the only friend ofnode
, and ensure that it offers all the operations that types deriving fromlist
will need as protected methods. In this approach, thelist
type serves as a proxy to thenode
class for all of is derived types.Have
node
be a protected internal type tolist
. The fact that it is internal tolist
and it is protected locks everyone outside of the hierarchy oflist
from using the type at all, all of the methods innode
can be public.Be friendly and trusty: leave the design as it is, and make some of the operations in
node
public to all. Trusting the users with the contents and document the invariants on which yourlist
class is built so that user code will know what operations not to perform.
I prefer the first option, as it provides the list with the responsibility of managing the nodes, which is a good thing, at least better that sharing responsibilities... there is a single point where things can go wrong: the list
class, and it is up to that class to maintain its own invariants.
As an idea, using Mac's answer:
Declare a class called NodeAccess, NodeAccess contains the Node class declared under protected (like Mac's answer).
Declare the functions in node as public.
class NodeAccess
{
protected:
class Node
{
public:
void Function(){}
};
};
Then for every class that wants access to the node, they inherit NodeAccess as protected, which grants them and all other subclasses access rights to node within the protected ruleset, but prevents any other class from accessing node directly.
class Helper: protected NodeAccess
{
};
class OtherHelper: protected Helper
{
};
//etc
精彩评论