Inheriting from a class but using a subclass of an attribute - c++

I have to implement a Red/Black tree (RBTree) in C++, inheriting from a Binary Search Tree (BSTree) class I already created.
The BSTree class contains a Node pointer (Node is a class I created for BSTree) to the tree root.
I want to create a Node subclass called "RBTNode", which contains color attribute and related methods (so RBTNode is subclass of Node), then I want to create the RBTree class inheriting from BSTree, but with the new RBTNode instead of the standard Node.
The structure would be as follows:
BSTree contains Node;
RBTNode is subclass of Node;
RBTree is subclass of BSTree;
RBTree contains RBTNode;
How could I achieve that?

As suggested by Jarod42 in the comments, you can achieve this by making the node type a template parameter for the BSTree class.
Say you have these two node classes:
template<typename KeyT>
class BSNode {
public:
KeyT key;
// ...
};
template<typename KeyT>
class RBNode : public BSNode<KeyT> {
public:
bool color;
};
Then you could add a node type template parameter to BSTree and make it BSNode by default. You can then use RBNode while inheriting in RBTree.
template <typename KeyT, typename NodeT = BSNode<KeyT>>
class BSTree {
protected:
NodeT *root;
};
template <typename KeyT>
class RBTree : public BSTree<KeyT, RBNode<KeyT>> {
// root will be of type RBNode<KeyT>* here
};

Related

How to inherit a red black tree from a normal bst

I'm having a gigantic trouble with inheritance. I have a normal node as follows (please, ignore any typo in the code, I do not have it right now, but it compiles fine)
template<typename T>
class Node {
Node<T> *parent, *left, *right;
...//simple methods
}
then, I implement a normal BST using the node I just created:
template<typename T>
class tree {
virtual Node<T>* insert(T value);
...// other methods of tree
}
now I want to make a red black tree, but the code for it is almost the same, so I just try to override, say, insert:
template<typename T>
class rb_node : public node<T> {
int color;
...//methods to retrieve and set the color as well the constructor
}
template<typename T>
class rb_tree : public tree<T> {
Node<T> *insert(T value){
auto z = (rb_node<T>*)tree<T>::insert(value);
while(z->parent()->color() == RED)...
}
since I cast, the z->parent() is recognized as a rb_node, but the parent don't since it was constructed in the base class, so it does not have the color() method. How do I solve this problem that is killing me for almost two weeks??
Obs: if anyone need, my code is at https://github.com/dodonut/Algorithms/tree/master/Data_Structures.
I tried to override the variables of node to rb_node on constructor(but cannot cast nullptr), on the method inside rb_node to return rb_node(but the signature of base class methods is different)
One possible solution might be to have the base tree class also take an optional NodeType template argument? As in
template<typename T, typename NodeT = Node<T>>
class tree
{
...
virtual NodeT* insert(T const& value);
...
};
Then the sub-class could use its special rb_node:
template<typename T>
class rb_tree : public tree<T, rb_node<T>>
{
...
rb_node<T>* insert(T const& value) override;
...
};

Call child method from parent, when child is a template

I have this college project where I have to create a BinarySearchTree class using templates. We have to read a file and create the tree depending of the data type in the file. I made a parent class for the tree called BST so I can use the tree without giving it a class type.
class BST{
public:
BST();
~BST();
}
And the tree
template <class T> class BinarySearchTree : public BST{
public:
void add(T val);
}
And I wanted to do this:
BST tree = BinarySearchTree<int>(); //just an example, it can be of any type
tree.add(5); //doesn't work
How can I call "add" from BST without giving a specific variable type?
You have to make a virtual method in the class BST and also make BST a template.
virtual void add(T val) = 0;
Use CRTP(Curiously Reccursive/Reccuring Template Pattern) and Concept Pattern.
https://qiita.com/Riyaaaa_a/items/a9af401520f238f45b80
This is written in Japanese, however, it's interesting!

Container implementation using templates and inheritance

I'm trying to implement a generic ranked tree container by inheriting a basic 2-3 tree container
basic tree is declared as follows :
template<typename T>
class Node{
// etc..
}
template<typename T>
class Tree{
Node* root;
// etc
}
and suppose i wanted to implement a tree of integers, i though i could declare a class as follows :
class RankedNode : public Node<int>{
// ...
}
class RankedTree : public Tree<int>{
RankedNode root*; // for example
// ...
}
The class RankedNode will include additional fields to the class Node, that aid in fast traversal of the tree ( O(log n) ) , and by using inheritance i'll be able to prevent code duplication.
However, i don't know how to go about doing so correctly, any ideas would be appreciated :)
You could start by making Tree a template on N, (the node type), instead of T (the value type):
template<typename T>
class Node{
// etc..
}
template<typename N>
class Tree{
N* root;
// etc
}
This way you could write
class RankedNode : public Node<int>{
// ...
}
class RankedTree : public Tree<RankedNode>{
// RankedNode* root; <- remove this; it is already in Tree<RankedNode>
// ...
}
and add only fields that are really new compared to base classes.

How do I change a class to a template class?

I need to change the first line to : template <class T> class Node{
class Node {
private:
double data;
Node* next;
public:
Node(double);
virtual ~Node(); //for later use of polymorphismi, review the topic again
friend class Stack; // allows dStack for private member access
};
Node::Node(double data) {
this->data = data;
next = 0;
}
Node::~Node() {
}
but i am unsure of all the internal work i need to change. Do i just need to change the private data member and the public Node function?
I think what you are looking for is something along the lines of the following:
template<typename T>
class Node
{
private:
T data;
Node* next;
public:
Node(const T& d);
virtual ~Node();
// ... etc
};
Note that you will either need to implement the template class inline, in the same file, or include the implementation at the bottom of the header file.
The point is that you change your class so that it can be used for other types except double, for example int, float etc in the same way. If we think of it in more abstractly, you need to use the class for objects of type T, where T can be any of the types mentioned above (or even more).
So, in general, you need to put template <class T> (Setting it as a template class) before your class and replace double with T type.
for class declaration:
template<typename T>
class Node
for class functions implementation:
template<typename T>
Node<T>::Node()

C++ Defining a specific object type when extending a template class

I have written a short template list class defining some methods I would like to use in implementations of it. My current problem is that I am having trouble extending the generic template type and defining a specific type.
In other words, assume I have a class called MyType
List.h:
template<class T>
class List
{
public:
Node<T> *head;
Node<T> *tail;
...
}
Inside the Node class:
public:
virtual T getData();
I want to extend this class with a specific defined type MyType so that I can have getData() behave differently in the extended class MyTypeList. I am having trouble with syntax. Any help would be greatly appreciated!
class MyTypeList : public List<T>
{
...
}
You can do something like this:
struct MyTypeList : List<MyType> {
};
although it is about the same as doing:
typedef List<MyType> MyTypeList;