Class hierarchy Loop - High Level Design Suggestions - c++

I need a little assistance with high level design of this program.
I am manually creating class objects based on an XML description. It has nodes which define settings of a piece of hardware. The trouble is the nodes in the XML can simply point to other nodes by name. To be able to find the address of these node objects quickly based on name, I am using a map. This is simplified view:
class XMLfile
{
public:
Node* GetNode(const string FeatName); //Searches through "nodes" map to get pointer to Node
private:
map<std::string, Node*> nodes;
};
Then I define nodes as follows:
class Node
{
public:
virtual int GetValue();
virtual int Load(XML_type);
};
Then depending on the exact "type" of node, I create a few derived classes with additional variables.
class Integer: public Node
{
int IntegerSpecificVar;
int GetValue();
int Load(XML_type);
private:
int Value;
string p_Value;
};
The XML can be one of the two:
<Value>5</value> Which my object load will load 5 into int Value.
or
<p_Value>NodeName</p_Value> Which my object loader will load the string into p_Value.
Depending on the object in the XML, the GetValue() returns the int Value, or a pointer to a string with a different nodename. If its a pointer, I need to get the pointer to that node and then call GetValue on that object. What I really want to do is call XML::GetNode(nodename") but this is out of context.
One idea to get my Node objects access to that map is to create the class Node which is derived from the XMLfile:
class Node: public XMLfile
then I get circular references since it has not loaded yet. If I switch the order between class Node and class XMLfile, then XMLfile doesn't know what a Node class/type is. Note this is all in one big file for now.
IF anyone can offer general suggestions how to better arrange this it would be appreciated.

It's bad idea to think of a Node as an specified case of XMLfile, so don't derive one from the other. Inheritance means the relationship of A 'is-a' B.

Quick and possibly dirty solutions:
make the map a parameter of GetValue, or
store a (const) reference or pointer to the map inside Node.

Related

How to decide which methods belong where? C++

I finished writing an AVL tree, and one of the things that bothered me when programming it is deciding which methods belong to which class:
template <class ValueType,class CompareFunction>
class avlTree{
class avlTreeException{};
public:
class ElementDoesntExist : public avlTreeException{};
class EmptyTree : public avlTreeException{};
class ElementAlreadyExists : public avlTreeException{};
private:
class Node{
friend class avlTree;
ValueType* data;
Node *sonA,*sonB,*dad;
int height,balance;
private:
CompareFunction compare;
int treeSize;
Node* root;
};
(I removed the public\private methods to save space).
For some methods I think I made the right choice: update is a method of Node (updates height,etc).
Insert/remove are functions of the tree.
But for example the function destroyNodeTree(Node*) which is used by the tree destructor. What I did is to have destroyNodeList() call destroyNodeTree(root)
template <class ValueType,class CompareFunction>
void avlTree<ValueType,CompareFunction>::avlTree::destroyNodeTree(Node* rooty) {
if(!rooty){
return;
}
Node *A=rooty->sonA,*B = rooty->sonB;
destroyNodeTree(A);
destroyNodeTree(B);
}
However, I could have made destroyNodeTree() a method of Node, and call it on the root from the destructor (it would be implemented in the same way).
I had a similar issue deciding where the method findNode(const ValueType&) should go, meaning it obviously is a public method of tree, but should I create a method for Node with the same name and have the tree function call the node method on the root? Is it even acceptable to have a public function and an inner class method with the same name?
In my opinion it's better to have it as a method of nodes because that gives more flexibility (I'll be able to search for a node only under a certain node), but on the other hand that means that the method either needs to create an instance of class compare, or have each node keep a copy of an instance, or have class compare as a static function. Each of those has a disadvantage in my opinion though: creating an instance can be costly, keeping a copy can be costly, and forcing the user to make the function static doesn't seem right to me (but I'm horribly inexperienced so fix me if I'm wrong).
In any case I eventually made findNode a treeFunction only and not a method (the HW assignment didn't need the tree to able to search from a specific node so it doesn't make any difference there) but I don't want to write bad code.
To conclude, how do we decide where to save performance,memory,flexibility of the user (would he rather be able to search from any node or create nonstatic compare functions?)

OOP: Designing a tree, dividing functionality between Node class and a Tree Class

I need to implement a custom tree class (using C++). Throughout my work I've seen many tree implementations. Some implemented a "super Node" class which was exposed to the user. An instance of which (root node) acted as the tree. Some exposed a tree class, which utilized a node class to construct a tree. Some used the node class as a pure data struct, leaving functionality such as tree construction to the tree class. Others put the construction - like node.Split(), into the node class.
Say you needed to design a binary tree (like a KD-tree). What would be the "best" approach from OOP perspective. Have node class just contain the data, or the logic to split itself into children? How much logic in general should a node class contain?
Thanks ahead for constructive input!
Here's one OOP rule you should always follow,
Every class represents an entity. Classes have properties and methods
i.e. the attributes of the entities and it's behaviour
So you need to follow your understanding of the scenario.
Here's how I look at a node.
It has some data, a right node reference and a left node reference. I don't think a node should be able to do anything except provide you with the data so I would write a node class something like this:
class Node
{
public:
int Data; // yeah, you would obviously use templates, so it's not restricted to a particular type
Node* Left;
Node* Right;
// also you can write constructors and maybe some sort of cast operator overload to be able to make the
// we could also make it return the subtree itself
getRightSubTree(){ return Tree(*Right); }
getLeftSubTree(){ return Tree(*Left); }
};
A Tree should be like this then.
class Tree
{
private:
Node root;
public:
Tree(Node t):root(t){} // every tree should have a root. Cannot be null.
// since the root node will be able to handle the tree structure, now we'll need the necessary methods
void addNode(Node n){
// code here
}
....
getSubTree(int data){
// check if node with that data exists and all
...
Node n = getNode(data);
return Tree(n);
}
};
Okay so I think you've got an idea now. It's all about how you look at the system.

class object also managing a tree structure?

I'm working on a class hierachy, where an object of a class may contain several objects of the same class.
This would lead to a tree structure:
class myClass
{
myClass *parent;
std::vector<std::unique_ptr<myClass> > childs;
/*
* here are some more attributes which describe a myClass object
* but are not related to the tree structure.
* std::string name; for example
*/
public:
//constructors...
//tree management functions
//some more members...
}
However, after thinking about it for a while, i think this is bad practise.
In this approach, myClass not only needs to have members related to its actual behaviour but also for managing the tree, like searching or inserting childs. This would be a lot of different functionality in one single class.
And, as we are lazy programmers, I don't like to re-invent the wheel.
There are some tree-containers out there, for example the well-known "tree.hpp".
Why not using this container for storing the myClass objects?
Well, problem is, some members ob myClass require access to its parents.
Imagine a member-function like getFullName(), which returns not only the "name"-attribute but a complete path to the actual object(all the parent's names). So this function would need to iterate trough all parent nodes until root is reached.
I'm not sure how i can achieve this using tree.hpp or similar containers.
Does myClass then need to store a pointer to the tree-node which contains it?
But I cannot think of an example where an object has information about the container containing it. An object of a class should not know anything of "being contained". Or am I wrong?
Maybe my first approach (myClass does also the tree management) is even OK?
OK, maybe i should ask a simplier question:
What is a good way to let an object know its own position within a container, e.g. a tree?
What is a good way to let an object access its parent in without storing to much (redundant) information in the object itself?
First of all, this is wrong:
class myClass
{
myClass *parent;
std::vector<std::unique_ptr<myClass> > childs;
};
Your children should be stored as a vector of shared_ptr, and the parent should be a weak_ptr.
class myClass
{
std::sweak_ptr<myClass> parent;
std::vector<std::shared_ptr<myClass> > children;
};
However, it looks like what you want is a template tree container. So your class should look like this:
class myClass
{
/*
* here are some more attributes which describe a myClass object
* but are not related to the tree structure.
* std::string name; for example
*/
public:
//constructors...
//tree management functions
//some more members...
};
And the tree container should be something like this (conceptually):
template <typename T>
class tree
{
std::sweak_ptr<tree> parent;
std::vector<std::shared_ptr<tree> > children;
T value;
};
This tree can be generic and hold different types of objects, including myClass.

c++ class refers to each other

I have a class
class PCB {
public:
struct {
string type;
**linklist list;**//refer to list which contains PCB instance
} status;
}
what i want is to create the class PCB instance, but the instance is in a linklist list. i build the linklist class as below
class linklist
{
public:
void append( PCB num );
};
void linklist::append(PCB num){
}
Error occus saying num above is in error type. what shall i do in this case?
If you do not need the copy in your linklist::append method you could as well just use a (const) reference
void append(const PCB& num);
and forward declare PCB before in the same header file
class PCB;
You could do a forward declaration on one of the types but your really should ask yourself why you are doing this.
I cannot think of any time when this would be a good idea. If you think about your problem relative to the real world linklist is a collection of buckets. What you are asking for is a bucket (PCB) to hold a series (linklist) of buckets (PCB). In reality this would never work as a bucket cannot hold a collection of other buckets of the same size.
Another think to ask yourself, why would you use a link list when the STL (Standard Template Library) provides everything you would need and more already. I would highly recommend a vector if you list of PCB's are fairly static, or a list if not.
Linked lists can be very efficient for lightweight containers but you have to maintain them. If you using classes, GO WITH STL containers.
You can use forward declaration:
class linklist; // forward declaration
class PCB {
public:
struct {
string type;
linklist list; //refer to list which contains PCB instance
} status;
}
Or when you only refer to a type by reference or by pointer, you do not need to include it's header file.
linklist* list
You need to forward-declare each class before defining the other. In the header that defines PCB, write
class linklist;
before the definition of PCB, and in the header that defines linklist, write
class PCB;
before the definition of linklist. That way, when the compiler encounters each of the class definitions, it'll know that the "other" class's name is valid and let you declare pointers to it even though it hasn't been fully defined yet.
Edit: Sorry, I just noticed that your linklist::append function actually takes a PCB instance, not a pointer. In that case you need to make sure that the PCB class is defined before linklist, but you still need to forward-declare linklist before PCB so that you can make pointers to it. The order of your code should be:
class linklist;
class PCB {
// involves pointers to linklist
;
class linklist {
// holds instances of PCB
};
Edit Again: I's misread your **linklist list as a pointer to a linklist (even though it's syntactically wrong).
What you need to do is:
Forward-declare PCB so that the definition of linklist can refer to it in a method signature.
Define the linklist class, but not its append function yet.
Define the PCB class, which can contain an instance of linklist since that class is now fully-defined.
Define the linklist::append() function, which can take an instance of PCB since that class is now fully-defined.
That'll get your code to compile, but it won't do what you probably want it to, because the way you've defined your classes doesn't make much sense. Your PCB class doesn't "refer" to a list, it contains a list within it. Since that list member variable isn't a pointer, every PCB instance contains an entire linklist. When you append() a PCB to a linklist, you're making a copy of that whole PCB, including the (different) linklist that it contains.
I have a feeling you're coming from Java or C# and you're assuming that things are references when they really aren't. You need to learn about how to use pointers.

Implementing General Tree

I came across the following code and despite some help from others, I am still having trouble understanding it.
This code is supposed to implement a General Tree. Single_List and Single_Node classes are also available for use in implementation.
template <class Object>
class General_tree {
private:
Object element; // the stored in the node
Single_list< General_tree<Object> * > children;
// a linked list of pointers to general trees
public:
Object retrieve() {
return element;
}
// ...
};
Can someone tell me what one instance of this class will consist of?
I think it will consist of
[element value in node made by Single_Node] ----->
/ next pointer (part of Single_list class)
/
/ children pointer to another such instance of General_Tree
V
Then these instances can be combined to form a tree... I am still getting used to Object Oriented Design I guess so please let me know if this reasoning and interpretation is correct?
thanks!
The tree object is really a node in the tree, where children points to the nodes at the next level, which will have pointers to their children, etc.
Together they form a subtree (or the whole tree, if it is the root node).