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 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 List, list may access its private/protected members and functions. It also helps to highlight the functional relationship between the two classes. This probably takes care of all your dot points except the third.
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 of node, and ensure that it offers all the operations that types deriving from list will need as protected methods. In this approach, the list type serves as a proxy to the node class for all of is derived types.
Have node be a protected internal type to list. The fact that it is internal to list and it is protected locks everyone outside of the hierarchy of list from using the type at all, all of the methods in node 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 your list 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
Related
I am currently in the process of coding my B+ Tree and this is the structure of my code for reference so that my proceeding question makes more sense:
Class BPlusTree{
// some functions, members.. etc
};
Class Node{
// some functions, members.. etc
}
Now, here is my question/dilemma, since my Node is a class of its own, if I want to insert a key/value pair into a node, I would have to call the BPlusTree insert function which in turn calls the Node's own insert function ( I cannot access Node's private members directly). This seems a bit weird to me.
However, if I were to simply do this in my Node Class:
friend class BPlusTree;
I would be able to access Node's private members and thus I do not need to make an insert function inside the Node class because now my BPlusTree insert function has access to the members.
Is this approach good or bad? I'm at the point where refactoring my code isn't going to be a pain so I thought I'd ask this now before it's too late.
Adding the insert() in the Node class isn't bad at all. If it does look weird to you when BPlusTree::insert() calls Node::insert() please don't be there are quite some advantages to this style of code.
My answer could be opinion based.
With the Node::insert() node is much more complete and is a full fledged class on its own. The Node class can be used by many other classes that you might make in the future. So you won't have to write the insert() function again and again.
Modularity is exactly what the above paragraph means. Your code becomes much more modular this way.
I'm not against friending the BPlusTree class but the thing is that the day you make BPlusTreeImproved or anything that uses Node you'll have to friend that as well to use the Node. Which means constant pain of changing and recompiling Node.
We have two classes(A and B). Class A can only be created by classes who inherit from it(class A)
and class B can be created by a user.
Class A, version 1 has a private data member and has methods to aces the data in class A.
Class A, version 2 has a protected data member and therefore, no methods are needed for classes that will inherit from the class to aces the data in class A
Class A, version 1
class A
{
protected:
A() = default;
void set_data( T d );
T& get_data();
private:
T data;
}
Class A, version 2
class A
{
protected:
A() = default;
T data;
}
Class B
class B : public A {}
Which version of class A is the preferred one?
This is fairly subjective, but I would say 95% of the time neither one. Protected data makes your code just as hard to maintain as public so we rule that version out right away. But then also you almost never need a direct mutator (set) function, so we'll chop that function and then change the signature of the get function to const T& get_data() const;. Then we'll add a real interface to the parent to manipulate its state rather than having something external decide what the new state should be.
Your version one is always preferred. Data members of class should by default be private. Making data members all public is justified only in one case i.e If you just want to bundle-o-data. Only then you would use struct and make all data public. ( Like to capture the essence of what is s single node in linked list)
However, there is no such exception in case of protected. You can always make them private and provide accessors/mutators to those data members.
Downside of public data members is that they breaks the encapsulation. And it's difficult to maintain invariants as data is open to modification from all sides. Case of protected data member is bit restrictive than public in that it opens up ways for modification only through derived class members and friends. But still it's breaking encapsulation.
Conclusion :- All data members of class should always be private except in case it's intended to be used as bundle-o-data.
Along with that you would never want to pass handle to your internals to outside users as you have done in:-
T& get_data();
So, better way would be
const T& get_data();
except in some specific scenarios.
If you follow the common guidelines, data members should be private. Therefore, version 1 is preferred. On the other hand, completely trivial get/set pairs are a minor code smell in my opinion, so you may want to investigate why that member needs to be fully exposed to the derived class in the first place.
Use accessor functions if you need anything other than simple access to the variable: validating the value, maintaining class invariants, signalling changes, logging, etc. Note that get should return either a value or a const reference; your version, returning a non-const reference, can be used to assign arbitrary values to the variable, bypassing the set function.
If you only need simple access then some would suggest exposing the variable for the sake of simplicity; others would suggest using accessor functions for the sake of consistency (with other types that do need such things), or backwards compatibility (if you later decide you need functions after all). There's no compelling reason to prefer either option.
I am using C++ under Ubuntu 11.10 and the latest version of NetBeans. Let's say I have the
following code:
class Node {}
class DerivedNode : public Node {}
class Graph {
vector<Node*> nodes;
}
class DerivedGraph : public Graph { }
At the moment I'm storing DerivedNodes in the DerivedGraph class like this for example:
nodes.push_back(new DerivedNode());
When I need to use specific methods that only apply to DerivedNodes and DerivedGraphs
I am forced to use a dynamic_cast on my Node pointers first.
I would like to be able to have specific methods in DerivedGraph which apply only to DerivedNodes
and avoid the need of casting pointers. I do not mind having to redesign my classes if the end
result is better than what I have.
I am sure there must be a clean and simple method to achieve the same thing I'm trying to do.
Maybe something with specialized templates? Any thoughts on the matter would be greatly
appreciated. I'll also provide any additional information required in the case I haven't been too
clear.
EDIT: I don't have two copies. I wanted to put emphasis on how it looks. I apologize for the presentation. What I want to obtain is:
class DerivedGraph: public Graph {
vector<DerivedNode*> nodes;
}
Are you sure that your interface in Node is appropriate? Sometimes when you find yourself needing to downcast (especially in a case like this where base pointers are stored in a container) that may be a signal that your abstract interface doesn't cover all your needs properly. Often something like the Template Method pattern solves all your needs without needing a downcast at all.
However, assuming that your inheritance model really need work in such a way, what you probably want to do is have virtual methods that get overridden in DerivedGraph for adding and getting nodes. You will have to verify the node type and downcast it in this case.
One final approach is to have two separate containers, one in the parent that contains all nodes that aren't DerivedNode and then another container in DerivedGraph that contains all the DerivedNode. Then you use overridden functions again to determine which container to access depending on your API needs.
Start by not duplicating your data member in the derived class.
Then add virtual member functions that you use to add data to your container. That way you can create instances of derived types in the derived class and add them to the container.
Finally, when you override the virtual function that returns a reference to data in the derived class, use covariant return types.
I have a main class that is inherited by numerous subclasses. The inherited main class has to be at least protected in inheritance to prevent non-derivative classes from using or altering it via the subclasses.
Is there a way to permit the various subclasses to alter each other's inherited main class variables, but without permitting public access to the main class? And without using the friend keyword given this would produce complicated code.
In full context:
I have a node class that add/remove nodes relative to it. There is a list class (and subclasses) that rely upon the node class, which means the node cannot be publicly accessible in-case it also breaks the class list. Node has to also be accessible to list helper classes.
To ensure that occurs, I implemented node under protected inside another class, accessnode. All classes wanting rights to node inherit accessnode as protected (so the accessnode class isn't public). This means the helper and the list class/subclasses all gain access to node.
The problem is, in order for TemplateList to copy CharList (a subclass of TemplateList) via read-only, it needs access to the nodes of CharList (to avoid using CharList's iterator) - the problem is, the nodes are protected (to prevent external, non-accessnode interference), and implementing a public method that grants access to the nodes would defeat the point.
What I need is sideways inheritance, so all subclasses of type accessnode can access each other's node without granting access publicly.
In short:
(Protected)Node inside AccessNode.
TemplateList : Protected AccessNode.
CharList : Protected AccessNode.
TemplateList needs to access CharList's AccessNode.
AccessNode/Node cannot be public.
Disclaimer: This is quite unrelated to this particular question, but more on the general problem that lead you to this and the other questions from today.
I think that you are barking at the wrong tree here. I get the feeling that you provide access to your list's internal nodes, and then expect that the node type itself protects the list from careless modifications (i.e. those that could break the invariants of the list). In doing so, you are pursuing a complex solution to a much simpler problem: do not let users access the node in the first place.
Things become much simpler if you look at the approach provided by the STL regarding containers and in particular lists. The list is implemented in terms of some unknown innaccessible nodes. The access specifiers on the operations of those nodes don't matter at all, since users cannot gain access to the object itself, so they can be public. Users gain access to the contents of the list through a different proxy (iterator, const_iterator types) that provides only those operations that cannot mess the state of the list.
I'm not completely sure I understand what you mean by "subclasses [to] alter each other's inherited main class variables".
If you want to allow access to a base class member variable by derived classes only then make the member variable protected. And/or add a protected accessor function.
If you want different instances of the derived classes to modify shared data held in the base class then you could add a static protected member variable to the base class. All instances would share the same member variable.
It would help if you clarified the problem.
You can always just add a protected accessor function in the top level class, but rather than do that it would probably be much better to rethink the design.
EDIT: concrete example:
class Base
{
protected:
struct State
{
int m1;
char m2;
State(): m1(), m2() {}
};
State state_;
static State& state( Base& o) { return o.state_; }
};
class Derived
: public Base
{
public:
void foo( Base& other )
{
Base::State& baseState = state( other );
// Blah blah.
}
};
int main()
{
Derived o;
// Blah blah.
}
Cheers & hth.,
what is the best way to put a container class or a some other class inside a class as private or a public member?
Requirements:
1.Vector< someclass> inside my class
2.Add and count of vector is needed interface
If the container's state is part of the class's invariant, then it should, if possible, be private.
For example, if the container represents a three dimensional vector then part of the invariant might be that it always contains exactly 3 numbers. Exposing it as a public member would allow code external to the class to change the containers size, which in turn could cause problems for any routine which requires the container's size to be constant. Keeping the container private limits the places in your software where the container's size can be modified to the class's member functions.
Whether a member is declared Private or Public depends entirely on your application. Could you give some more detail?
One important point to remember when declaring your member is that if you provide a "getter" to retrieve it, then you are no longer encapsulating that object. Instead, it can be good to write wrapper methods exposing only the functionality you wish to expose.
For example, with a Vector member, you might write an AddItem and Clear method, if that's all the functionality you wish to expose.
Since you're talking about a class, I think it should be private. If you want it to be public, rather create a struct - to make it obvious that you want the members variables to be used.
A viable alternative to exposing the vector member is creating a visitor function (or an internal iterator). This way you obey the law of Demeter better:
class ContWrapper {
std::vector<int> _ints;
public:
class Action {
public:
virtual void accept( int i ) = 0;
};
void each_int( Action& a );
};
Also be very careful when exporting e.g. an std::vector<T> from a library, too: the client code might not use the same STL implementation as you did, so the layout of these member variables may differ!
Make all members private and use accessor methods, this allows you to change the implementation later. Only in very unusual circumstances would I make any data member public.
Remember that chaning the implementation happens more often than you may imagine, its not just a case of changing the type of the container but maybe you want to change the mechanism. Say you were storing names in a list, after a while you may chose to index this list with a hash and would like to have the hash updated every time you add a new name. If your implementation is suitably encapsulated doing this is easy, if you have just exposed the vector you would need to make changes that will adjust the interface (and so the change will ripple out).
If this is new to new you have a read of: http://en.wikipedia.org/wiki/Encapsulation_(classes_-_computers)
There is a third way - sometimes it is better to inherit from the container and override it's methods to achieve your goal (for example thread safety). Anyway, making it public almost always isn't a good idea.
Considering that you want to encapsulate the container inside another class implies that it cannot be public, and also the public methods of your class should not expose anything implementation-specific about the container. That way the implementation of your class (i.e. the container) can be changed without changing its interface.