Inheritance with Nodes in C++ - c++

I'm writing a doubly linked list in C++ and have a class Node which I'm using for a singly linked list. Below shows the definition of the class.
Node.h
#ifndef NODE_H
#define NODE_H
template <class T>
class Node {
public:
Node<T>() { next = nullptr; }
Node<T>(T init) { data = init; next = nullptr; }
void setData(T newData) { data = newData; }
void setNext(Node<T> *nextNode) { next = nextNode; }
const T getData() { return data; }
Node<T> *getNext() { return next; }
private:
T data;
Node<T> *next;
};
#endif
Obviously the main difference between a singly linked list and doubly linked list is a pointer to the previous Node, so I'm trying to inherit everything from the Node class in a new class and simply add a prev attribute:
DoublyLinkedList.h
#ifndef DOUBLY_LINKEDLIST_H
#define DOUBLY_LINKEDLIST_H
#include "Node.h"
template <class T>
class DLLNode : public Node {
public:
// Inherit default constructor from Node and set prev to nullptr;
DLLNode<T>() : Node<T>(), prev() {}
// Inherit constructor from Node and set prev to nullptr;
DLLNode<T>(T init) : Node<T>(init), prev() {}
Node<T> *getPrev() { return prev; }
private:
Node<T> *prev;
};
/*
TODO: Implement doubly linked list class
*/
#endif
My driver is, simply, the following:
driver.cc
#include <iostream>
#include "DoublyLinkedList.h"
int main()
{
DLLNode<int> test;
return 0;
}
When I compile, I get the following errors:
./DoublyLinkedList.h:7:24: error: expected class name
class DLLNode : public Node {
^
./DoublyLinkedList.h:9:18: error: type 'Node<int>' is not a direct or virtual base of 'DLLNode<int>'
DLLNode<T>() : Node<T>(), prev() {}
^~~~~~~
driver.cc:6:15: note: in instantiation of member function 'DLLNode<int>::DLLNode' requested here
DLLNode<int> test;
I don't understand why the class Node isn't being recognized as a class as my compiler has claimed by the first error. Any tips would be greatly appreciated.
My compiler is Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)

You need to pass the template type parameter to your templated base class, when inheriting:
template <typename T>
class DLLNode : public Node<T> {
// ^^^
// ...
};

Related

Initialization of a struct defined in a templated parent class

I have defined a struct within the protected section of a parent class, which I would like to use in an inherited class.
This works as expected if the parent/child classes aren't templated classes. But does not compile as-is below.
Specifically, the compiler (clang 8.0.1) reports:
inheritance_example.cpp:33:26: error: unknown type name 'Node'
this->head = new Node(toAdd);
From what I have read, I am guessing that the template type specification isn't being assigned to Node, and is thus not being found by the inherited class, but trying the fixes I have found in that vein (i.e. add something along the lines of using Parent<T>::Node, or add a type specifier to the call to the Node constructor), have not worked for me.
Any ideas on how to fix this issue?
#include<iostream>
template <class T>
class Parent
{
protected:
struct Node
{
Node(int value)
{
this->data = value;
this->next = nullptr;
};
~Node() {};
Node* next;
int data;
};
Node* head;
public:
Parent() {};
~Parent() {};
};
template <class T>
class Child : Parent<T>
{
public:
Child()
{
this->head = nullptr;
};
~Child()
{
delete this->head;
this->head = nullptr;
};
void dummyAdd(T toAdd) {
this->head = new Node(toAdd);
};
void dummyPrint()
{
std::cout << this->head->data << std::endl;
};
};
int main()
{
Child<int> t;
t.dummyAdd(5);
t.dummyPrint();
return 0;
}
In order to pack the comment into an answer!
Node is a depended name and hence you need to use keyword typename there. Meaning in the dummyAdd function, you need
void dummyAdd(T toAdd)
{
this->head = new typename Parent<T>::Node(toAdd);
// ^^^^^^^^^^^^^^^^^^^^
};
That is, however, a bit verbose/ more typing. Therefore providing a type alias for Node in the Child will be a good idea.
template <class T>
class Child : Parent<T>
{
using Node = typename Parent<T>::Node; // template type alias
public:
void dummyAdd(T toAdd)
{
this->head = new Node(toAdd); // now you can this
};
// other code...
};

Redefinition as different kind of symbol using friend class C++14

I am trying to write a template for a class. This class uses a Node class within it so I have defined the Node class as having the List class as a friend. See below.
template <typename T>
class Node {
private:
Node() {
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList {
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node *_head;
Node *_tail;
};
I have another file where the classes are implemented. I get this error with or without the template definition above the List class. Can someone explain this?
This works for me:
template <typename T>
class Node
{
private:
Node()
{
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
template<typename T> friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList
{
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node<T> *_head;
Node<T> *_tail;
};

C++: Accessing class properties in header implementation file

I am trying to implement the doubly linkedlist data structure, so I created a class that has a private property node of type Node, when I try to access this property from a function implementation using this keyword the application fails. I need help
Header file for LinkedList.hpp
#include <stdio.h>
template<class T>
class LinkedList{
private :
struct Node{
T value;
Node* next;
Node* prev;
}node;
public :
LinkedList();
LinkedList(T item);
void add(T item);
// void get();
// void insert();
// void remove();
};
Below is the implementation of the header file.
#include "LinkedList.hpp"
template<class T>
LinkedList<T>::LinkedList(){
}
template<class T>
LinkedList<T>::LinkedList(T item){
}
template <class T>
void LinkedList<T>::add(T item){
Node* node = new Node;
node->value = item;
node->prev = NULL;
//Where the error is being generated
node->next = this.node;
};
The error returned says:
/Users/mac/Documents/LinkedList/LinkedList/LinkedList.cpp:27:22: Member reference base type 'LinkedList<T> *' is not a structure or union
this is a pointer, as pointed out by the error message.
Use:
this->node

Implementing a helper class in a header file

say in a header file can I have a helper class fully defined and use it in the class file that includes the header. what is the correct way of doing it?
//HEader
class LinkedList() {
public:
LinkedList(int a);
private:
Node *root;
class Node {
int data;
Node *next;
};
};
//cpp file
#include "LinkedList"
LinkedList::LinkedList(int a) {
root = new Node();
root.data = a;
root->next = NULL;
}
when i try doing something like that it ends up saying Node is not a name of type in my header file.
That is totally fine. I made some fixes to your code.
LinkedList.h
class LinkedList
{
public:
LinkedList(int a);
private:
class Node {
public:
int data;
Node *next;
};
Node *root;
};
LinkedList.cpp
LinkedList::LinkedList(int a) {
root = new Node();
root->data = a;
root->next = NULL;
}
You tried to use Node before you even declared and defined it. Default access level in C++ classes is private, so you could not access private data members of Node in LinkedList constructor.

problems inheriting from a c++ template class

So I'm trying to work out how inheritance works when templates are in the mix. Most compilers really don't seem to have this figured out yet, so I'm having a little syntax difficulty. All the weird includes in SkipNode.h are from trying to get eclipse to stop yelling at me. I'm getting a syntax error when trying to declare the constructor in SkipNode.h, so any help here would be useful.
Here is node.h
#ifndef NODE_H_
#define NODE_H_
template<class T>
class Node
{
public:
Node(Node<T>* next, Node<T>* prev, T item);
virtual ~Node();
Node* getPrev() { return prev;};
Node* getNext() { return next;};
Node* getItem() { return item;};
void setItem(T item){Node<T>::item = item;};
void setNext(Node* next){Node<T>::next = next;};
void setPrev(Node* prev){Node<T>::prev = prev;};
private:
Node* next;
Node* prev;
T item;
};
Here is SkipNode.h, where skipnode inherits from Node.
#include "Node.h"
#include "Node.cpp"
#include "SkipNode.h"
#include "SkipNode.cpp"
template <class T>
class SkipNode: public Node
{
public:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item) : Node(next, prev, item);
virtual ~SkipNode();
Node* getChild(){return child;};
void setChild(Node* child){SkipNode::child = child;};
private:
Node *child;
};
#endif /* SKIPNODE_H_ */
Node is a template, you should pass in template parameter
template <class T>
class SkipNode: public Node<T>
// ^^^
Also you need to provide SkipNode constructor definition as you have provided member iniatilizer list.
update:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item)
: Node(next, prev, item);
To:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item)
: Node(next, prev, item)
{
}
You're missing an #endif in node.h and you need to provide the template parameter to your base class:
template <class T>
class SkipNode : public Node< T >
....
This level of indirection exists to allow inheritance from a template class by a class that has different (or zero) template parameters. For instance:
class Foo : public Node< int >