I have a treatment parent class, and two children, inner treatment and outer treatment. I need to create a single linked list that contains both of the children nodes. I'm not allowed to use templates, or built in lists.
The problem I'm facing is the type of the next ptr, the only solution I found is to create a base node parent type, and put the two children inside it, plus a type variable to know which kind of node it is. Something like this:
enum node_type = {inner, outer};
struct treatment_node{
Inner_Treatment t1;
Outer_treatment t2;
struct treatment_node *next;
node_type treatment_type;
}
I'll know which class to access based on the treatment type. Would this work?
As polymorphysm goes, you can use the same wording as in your question, but put a different meaning to the word 'base'. So, you can create a base treatment class and inherit your inner and outer classes from it:
class treatment_node {
treatment_node *next;
public:
virtual std::string getTreatment() = 0;
...
};
now your outer and inner:
class Outer_treatment : public treatment_node {
... members ...
public:
std::string getTreatement() override {...}
};
};
class Inner_treatment : public treatment_node {
... members ...
public:
std::string getTreatement() override {...}
};
Now you can put both on the list of treatement_nodes.
Related
I am trying to build an execution graph where each node can produce multiple outputs of different types and consume multiple inputs of different types. Data is transferred between the nodes via queues.
To connect 2 nodes, the input type of one node must be connected to the same output type of the other node. For example, trying to connect the int output of one node to the double input of another node should yield in a compilation error.
All nodes will derive from a base class that has a execute() method that reads from the different input types and writes into the different output types. Currently, I have something like this-
struct Node {
virtual void execute() = 0;
};
struct IntegerGeneratorNode: public Node {
void execute() {
while(some_condition_is_not_met) {
// write() will do std::queue<int>::push();
int_out.write(some_rand_integer);
}
}
Output<int> int_out;
};
struct FloatGeneratorNode: public Node {
void execute() {
while(some_condition_is_not_met) {
// write() will do std::queue<float>::push();
float_out.write(some_rand_float);
}
}
Output<float> float_out;
};
struct SinkNode: public Node {
void execute() {
while(some_condition) {
int val = int_inp.read(); // invokes queue<int>::front()+pop()
float f_val = float_inp.read();
// Do something with val and f_val.
}
}
Input<int> int_inp;
Input<float> float_inp;
};
Input<T> is a templated class that has a queue of type T. Output<T> is a templated class that has a pointer to a queue of type T. To connect 2 nodes, I do something like-
Node *int_node = IntegerGeneratorNode();
Node *float_node = FloatGeneratorNode();
Node *sink_node = SinkNode();
int_node.int_out.connect(sink_node.int_inp);
float_node.float_out.connect(sink_node.float_inpt);
std::thread int_thread([](Node *node){ node->execute(); }, int_node);
std::thread float_thread([](Node *node){ node->execute(); }, float_node);
std::thread sink_thread([](Node *node){ node->execute(); }, sink_node);
This works fine but I have another requirement- perform some operation on ALL the Input<T>s of a Node before the execute method is called - Input<T>::doSomePreProcessing(). As you can see, having named variables doesn't scale. You have to add a .doSomething on ALL the variables you have. I need some kind of looping.
One idea is to have a tuple of Input types and iterate the tuple using C++17 std::apply. But another major requirement I have is that the derived classes are client code and base class is framework code. All preprocessing must be done from the base class to lessen the burden the load on the derived classes. To do this I need to move the tuple to the base class like this-
template<typename T>
struct Node {
virtual void execute() = 0;
void doExecute {
preprocess(some_tuple);
execute();
}
T inputs() { return input_tuple; }
T input_tuple;
};
template<typename T>
struct SinkNode: public Node<T>{
...
};
// Call site.
SinkNode<std::tuple<int,float>> sink_node;
2 side-effects happened cos of this change
The base class is now templated and I can no longer have a common base class pointer which is required to invoke doExecute method on the nodes of the graph.
connect is hard to implement. Ideally what I am looking for is
template<typename T>
void connect(Node* src, Node* dest) {
std::get<T>(src.outputs()).connect(std::get<T>(dest.inputs()));
}
But since Node* is not available anymore, I can't do this.
How do I do all processing on the inputs in the base class yet have a common base class pointer? In other words not have it templated?
Several approaches come to mind:
Split off the virtual void execute() = 0 into a separate baseclass, from which you then derive the different, templated baseclasses.
Apply the Decorator Pattern: Just create a Node class that wraps another Node class. When the outer execute() is called, preprocess the input and then invoke the inner execute().
Use multiple inheritance. One base class might provide the execute() interface, another might provide the preprocessing interface. This is similar to the first variant, only that the two parts are not stacked on top of each other but rather next to each other on the same level.
For a school project, I need to build a BinarySearchTree for a tuple of index and value of type T and I decided to make it using left and right child pointers (to other instances but bear with me).
To make the class a bit more realistic and readable, I built 3 different classes: Tree, BinaryTree, and BinarySearchTree with inheritance.
I declared the getter and the setter of the left and right children in the BinaryTree class and the class looks like this:
template <typename T>
class ArbreBinaire : public Arbre<T>
{
private:
ArbreBinaire<T>* _leftChild;
ArbreBinaire<T>* _rightChild;
public:
ArbreBinaire(lu index = 0, T element = T(0), ArbreBinaire<T>* lchild = nullptr, ArbreBinaire<T>* rchild = nullptr) :
Arbre<T>(index, element), _leftChild(lchild), _rightChild(rchild) {};
virtual ArbreBinaire<T>* getLC() const { return _leftChild; }
virtual ArbreBinaire<T>* getRC() const { return _rightChild;}
void setLC(ArbreBinaire<T>* lc) { _leftChild = lc; lc->setParent(this); }
void setRC(ArbreBinaire<T>* rc) { _rightChild = rc; rc->setParent(this); }
virtual ~ArbreBinaire() = default;
};
And in my BinarySearchTree, in a few places I need to go through my tree (to insert or search for exemple).
So here comes finally my question: What is the best way to get the left child of my object, which is of type BinarySearchTree and to keep the continuity (BST that has BST left child and BST right child)
I thought of multiple options:
virtual getter and setter and redefining it in every derived class but there are 2 other "problems" with that solution.
Should I have 2 other members in my BST, which would be of type BST* and basically point to the same object than the ones in my BinaryTree ?
Should I just redefine my getters to return a dynamic_cast version like this : BST<T>* getLC() { return dynamic_cast<BST<T>*> (this->BinaryTree::getLC()) } ?
Putting all my members, getters and setters in my BST class (but that goes opposite to the definition of a BinaryTree, the base class : a BinaryTree with no children is not a BinaryTree)
3.Just casting every time i need to get my left or right child
4.Casting everytime i need to use a method in BST (derived class) ?
5. Any other suggestions?
Consider the following code:
class myclass
{
public:
//some public stuff
private:
struct classitem
{
int x;
classitem *next;
};
}
What I do not understand is this;
Is classitem just a definition, or will it already be a member of an object of this class? In other words, will it be filling any memory when we create an object of this class? If it is just a definition, how would we use it in future?
And what would be the benefits of using this struct in class definition instead of defining it outside of the class?
It will be just a definition.
If you want an object, use:
struct T { ... } instance;
The inner struct will be scoped in the outer struct definition - as to why it's useful, you can make the type (class) definition private for instance, if you don't want that type to be used outside of your class.
class NHeadedBeast {
struct Head {
Head() : numHeads{2}, eyesPerHead{4} { }
int numHeads;
int eyesPerHead;
} head;
public:
int getEyeCount() const {
return head.eyesPerHead * head.numHeads;
}
};
Notice how specific the Head class is - and also, it's called Head, which has a decent chance of colliding with some other type name. In other words, noone would ever want to use that Head type without my NHeadedBeast class, so might as well make the type inaccessible and isolate it in the NHeadedBeast scope.
The title might be a bit misleading. I have the following problem: I have a tree consisting of leaves and internal nodes. The user should be able to store any information in the leaves and the tree has some methods which get a set of user-defined values and need to access the corresponding leaves in constant time (not amortized).
I came up with the following idea but it does not work because unfortunately I cannot access private members of a nested class: The user creates the tree and also for each leaf an instance of UserElement which contains the user_defined value for the corresponding leaf. Once a method like doSomethingWithTheTree(list>) is called and the tree is built, the tree creates the corresponding leaves and saves it in the private field leaf. Whenever the user wants to call a method with some of the leaves corresponding to its user_defined values, he/she just has to call the method by giving the corresponding UserElements and the tree can retrieve the corresponding leaves in constant time.
class Tree {
public:
template <typename T>
class UserElement {
private:
T user_value;
tree_node* leaf; // this has to be private for
// everyone outside the class `Tree`
public:
T getInf() {
return user_value;
}
void setInf(T i) {
user_value = i;
}
};
void doSomethingWithTheTree(list<UserElement<T>> elements) {
...
// I want to be able to access elem.leaf for all elements
}
}
Technically, that's a nested class (declared within another class), not a subclass (which inherits from its superclass).
You can allow the Tree class to access its privates by making it a friend:
class UserElement {
friend class Tree;
// ...
};
or, for better encapsulation, you could restrict access only to the member function(s) that need it, although it gets a bit messy due to the need to declare things in the right order:
class Tree {
public:
// Declare this so we can declare the function
template <typename T> class UserElement;
// Declare this before defining `UserElement` so we can use it
// in the friend declaration
template <typename T>
void doSomethingWithTheTree(list<UserElement<T>> elements) {
elements.front().leaf;
}
template <typename T>
class UserElement {
// Finally, we can declare it a friend.
friend void Tree::doSomethingWithTheTree<T>(list<UserElement<T>>);
// ...
};
};
You may do
class Outer {
private: // maybe protected:
class Inner {
public:
....
};
};
or
class Outer {
public:
class Inner {
friend class Outer;
private:
....
};
};
You can declare class Tree a friend to UserElement<>, which would allow Tree to access all members of UserElement<>.
So suppose I have a tree class like this in c++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.
But this specialNode* has member variables and functions that Node doesn't have.
I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.
Is there any clever, or just any better way to go about this?
Other than literally casting every time?
If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node
Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Now, it should work.
If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:
specialNode* var = static_cast<specialNode*>(children[i]);
Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}
If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.
You can actually do the following:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.
You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.