So I've been playing around with Nodes and keep running into this error when I try to test it. If I use Parentheses I get this Error on list. - "Expression must have class type!"
If I don't use Parentheses I get this Error on list, insert and display - "this is inaccessible."
This happens when Declaring my LList in Main(). What's going on and why is this?
My Driver
#include "LList.h"
#include <iostream>
using namespace std;
int main()
{
LList<int> list;
bool test = list.insert(5);
list.display();
return 0;
}
Class LList
#include "Nodes.h"
#ifndef LLIST_H
#define LLIST_H
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
template<typename TYPE>
LList<TYPE>::LList()
{
front = null;
};
template<typename TYPE>
LList<TYPE>::~LList()
{
Node<TYPE>* temp;
while(front)
{
temp = front;
front = fornt -> next;
delete temp;
}
};
template<typename TYPE>
bool LList<TYPE>::insert(const TYPE& dataIn)
{
bool success = false;
Node<TYPE> pBefore = null;
Node<TYPE> pAfter = front;
while(pAfter && PAfter->data < dataIn)
{
pBefore = pAfter;
pAfter = pAfter->next;
}
if(Node<TYPE>* store = new Node<TYPE>)
store->data = dataIn
return success;
};
template<typename TYPE>
void LList<TYPE>::display() const
{
TYPE* temp = front;
while(front && temp->next != null)
{
cout << temp->data << endl;
}
};
#endif
Class Nodes
#ifndef NODES_H
#define NODES_H
template<typename TYPE>
struct Node
{
Node<TYPE>* next;
TYPE data;
Node();
Node(TYPE d, Node<TYPE> n);
};
template<typename TYPE>
Node<TYPE>::Node()
{
data = 0;
next = null;
};
template<typename TYPE>
Node<TYPE>::Node(TYPE d, Node<TYPE> n)
{
data = d;
next = n;
};
#endif
Your errors are a result of your class declaration:
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
The clue is in the error "This is inaccesible." Because you have not given any access modifiers, all of the members of this class default to private. To fix this, you just need to label the public and private sections of your class:
template<typename TYPE>
class LList
{
public:
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
private:
Node<TYPE>* front;
};
With this change, your code should work with or without parentheses at the end of your variable declaration for list.
Related
I get an initialization error for a TreeNode class constructor… This is the function:
TreeNode* a = new TreeNodens; Is the issue here, not sure what I have to add to TreeNode but it needs some type of tweak!
template <typename T>
void ScapegoatST<T>::rebuild(TreeNode<T>* node){
int ns = getHeight(node);
TreeNode<T>* p = node->getParent();
TreeNode<T>* a = new TreeNode<T>[ns]();
TreeNode<T>* r;
packintoArray(node,a,0);
if (p == NULL){
r = buildBalanced(a,0,ns);
r->setParent(NULL);
} else if (p->getRight() == node){
TreeNode<T>* Tr = buildBalanced(a, 0, ns);
p->setRight(Tr);
p->getRight()->setParent(p);
} else {
p->setLeft(buildBalanced(a,0,ns));
p->getLeft()->setParent(p);
}
}
Here is the TreeNode.h:
#ifndef TREE_NODE_H
#define TREE_NODE_H
#include <cstdlib>
#include <iostream>
using namespace std;
template <typename T>
class TreeNode{
public:
TreeNode(T nData);
virtual ~TreeNode();
T getData();
TreeNode<T>* getLeft();
TreeNode<T>* getRight();
TreeNode<T>* getParent();
void setData(T nData);
void setLeft(TreeNode<T>* nleft){left=nleft;};
void setRight(TreeNode<T>* nright){right=nright;};
void setParent(TreeNode<T>* nparent){parent=nparent;};
template <typename S>
friend class ScapegoatST;
private:
T data;
TreeNode<T>* left;
TreeNode<T>* right;
TreeNode<T>* parent;
};
template <typename T>
TreeNode<T>::TreeNode(T nData){
data = nData;
left = NULL;
right = NULL;
}
template <typename T>
TreeNode<T>::~TreeNode(){
delete left;
delete right;
delete parent;
data = NULL;
}
template <typename T>
T TreeNode<T>::getData(){
return data;
}
template <typename T>
void TreeNode<T>::setData(T nData){
data = nData;
}
#endif
I tired creating a constructor for the array initialization but it wasn’t successful.
The issue here is that you've created the constructor TreeNode(T nData), which prevents the constructor with no arguments TreeNode() from being generated, but you call that constructor when you do new TreeNode<T>[ns]().
One solution would be to add a constructor TreeNode(), with a body like so:
template<typename T>
TreeNode<T>::TreeNode() {
left = NULL;
right = NULL;
}
This will mean that constructing a TreeNode with no nData will result in the node's data field being default-initialized (for primitive types, it will contain an undefined value, and for classes it will act like T() was called to construct the data value).
I implemented a linked-list called Node that had a function called freeData where it would perform a delete on the node given and any following nodes.
I wanted to implement it inside my own custom list class as a private member, but came up with this error in Visual Studio 2019:
C2672 'freeData': no matching overloaded function found
C2783 'void custom::freeData(list::Node*&): could not deduce template argument for 'T'
I don't know what to change for my freeData function header to accept a Node* as an argument. I pass the argument pHead in these functions: ~list() and clear().
The previous definition before embedding freeData into the list class was void freeData(Node <T>* &pHead).
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list() : numElements(0), pHead(NULL), pTail(NULL) { }
~list() { freeData(pHead); }
void clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
private:
struct Node;
Node* pHead;
Node* pTail;
int numElements;
};
template <class T>
struct list <T> :: Node
{
Node() : pNext(NULL), pPrev(NULL) {}
Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
template <class T>
void freeData(typename list <T>::Node*& pHead)
{
}
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
freedata() is a free-standing function. Unlike class methods, free-standing functions have to be declared before they can be used. But, you can't forward-declare freedata() in this case since its argument depends on a type that needs to know what freedata() is. Catch-22.
To fix that, you could break up the declarations and implementations of the list and Node class, eg:
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list();
~list();
void clear();
private:
struct Node
{
Node();
Node(const T& t);
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
Node* pHead;
Node* pTail;
int numElements;
};
template <class T>
void freeData(typename list <T>::Node*& pHead)
{
...
}
template <class T>
list<T>::list() : numElements(0), pHead(NULL), pTail(NULL) { }
template <class T>
list<T>::~list() { freeData(pHead); }
template <class T>
void list<T>::clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
template <class T>
list<T>::Node::Node() : pNext(NULL), pPrev(NULL) {}
template <class T>
list<T>::Node::Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
But really, there is no reason for freedata() to be a free-standing function in this example. It should be a member of the list class instead, eg:
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list() : numElements(0), pHead(NULL), pTail(NULL) { }
~list() { clear(); }
void clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
private:
struct Node
{
Node() : pNext(NULL), pPrev(NULL) {}
Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
Node* pHead;
Node* pTail;
int numElements;
static void freeData(Node*& pHead)
{
...
}
};
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Derived template-class access to base-class member-data
(3 answers)
Closed 3 years ago.
I'm coding a simple LinkedList class that is a child class to an abstract List class. After finishing the List class I started to code the LinkedList class, and I noticed that the compiler would not let me access the protected variables from the members of the List class directly, even though LinkedList is a child class of List. When I do not add the "this->" pointer before one of List's variables, I get an error that says the variable is not declared in the scope. I'm sure there is a simple explanation for this, but I can't figure out why the two protected variables in my List class and its members are not accessible from the members of the LinkedList class.
List:
template<typename T>
class List {
protected:
unsigned int numElements;
Node<T>* head;
public:
List();
~List();
virtual void append(T x) = 0;
virtual T remove() = 0;
virtual bool isEmpty();
};
template<typename T>
List<T>::List() {
numElements = 0;
head = NULL;
}
template<typename T>
List<T>::~List() {
while(NULL != head) {
Node<T>* newHead = head->getNext();
delete head;
head = newHead;
}
}
template<typename T>
bool List<T>::isEmpty() {
if (numElements)
return false;
return true;
}
LinkedList with one member example:
template<typename T>
class LinkedList: public List<T> {
public:
void append(T x);
T remove();
void append_tail(T x);
void insert(T x, int pos);
T remove_at(int pos);
void print();
int getNumElements();
};
template<typename T>
void LinkedList<T>::append(T x) {
// create a new node with its next as the head
Node<T>* appendNode = new Node<T>(x, this->head);
// set the head to this new node
this->head = appendNode;
this->numElements++;
}
Node class that is included (not very relevant)
#ifndef NODE_H
#define NODE_H
template<typename T>
class Node {
private:
T value;
Node * next;
public:
Node(T v, Node * n);
T getValue() const;
Node * getNext() const;
void setNext(Node * p);
};
template<typename T>
Node<T>::Node(T v, Node * n) {
value = v;
next = n;
}
template<typename T>
T Node<T>::getValue() const {
return value;
}
template<typename T>
Node<T>* Node<T>::getNext() const {
return next;
}
template<typename T>
void Node<T>::setNext(Node * n) {
this->next = n;
}
#endif
I have a binary search tree class (BST.h) and a node class (Node.h) of which works fine when I store data types such as integers in it. My problem is trying store class objects in my BST and use an attribute from the object as the key. My program also has a student class which contains studentID and studentName. How would I write an operator overload in my student class so every time my BST preforms operation on nodes, it will overload to the student.getID(), instead of operating on the object itself. I have the rough idea of what the overload function should look like but i don't know where it should go or if its coded correctly anyway.
//My attempt at an operator overload
bool operator< (const Student &s1, const Student &s2)
{
return s1.GetID < s2.GetID;
}
//Node.h
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
Node();
T data;
Node *left;
Node *right;
Node(T);
};
template<class T>
Node<T>::Node()
{
}
template<class T>
Node<T>::Node(T d)
{
data = d;
left = NULL;
right = NULL;
}
#endif //
//BST.h
#ifndef BST_H
#define BST_H
#include <iostream>
#include "Node.h"
#include <string>
using namespace std;
template<class T>
class BST
{
public:
BST();
void Insert(T);
Node<T> *Search(T);
void preOrder();
void inOrder();
void postOrder();
~BST();
private:
Node<T> *root;
void Insert(T , Node<T> *aNode);
Node<T> *Search(T, Node<T> *aNode);
void preOrder(Node<T> *aNode);
void inOrder(Node<T> *aNode);
void postOrder(Node<T> *aNode);
};
template<class T>
BST<T>::BST()
{
root = NULL;
}
template<class T>
void BST<T>::Insert(T data, Node<T> *aNode)
{
if (data < aNode->data)
{
if (aNode->left != NULL)
{
Insert(data, aNode->left);
}
else
{
aNode->left = new Node<T>(data);
aNode->left->left = NULL;
aNode->left->right = NULL;
}
}
else
{
if (data >= aNode->data)
{
if (aNode->right != NULL)
{
Insert(data, aNode->right);
}
else
{
aNode->right = new Node<T>(data);
aNode->right->left = NULL;
aNode->right->right = NULL;
}
}
}
}
template<class T>
void BST<T>::Insert(T data)
{
if (root != NULL)
{
Insert(data, root);
}
else
{
root = new Node<T>(data);
root->left = NULL;
root->right = NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data, Node<T> *aNode)
{
if (aNode != NULL)
{
if (data == aNode->data)
{
return aNode;
}
if (data < aNode->data)
{
return Search(data, aNode->left);
}
else
{
return Search(data, aNode->right);
}
}
else
{
return NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data)
{
return Search(data, root);
}
template<class T>
void BST<T>::preOrder()
{
preOrder(root);
}
template<class T>
void BST<T>::preOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
cout << aNode->data << " ";
preOrder(aNode->left);
preOrder(aNode->right);
}
}
template<class T>
void BST<T>::inOrder()
{
inOrder(root);
}
template<class T>
void BST<T>::inOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
inOrder(aNode->left);
cout << aNode->data << " ";
inOrder(aNode->right);
}
}
template<class T>
void BST<T>::postOrder()
{
postOrder(root);
}
template<class T>
void BST<T>::postOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
postOrder(aNode->left);
postOrder(aNode->right);
cout << aNode->data << " ";
}
}
template<class T>
BST<T>::~BST()
{
}
#endif // !BST_H
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student();
Student(string, int);
~Student();
int Student::GetID();
private:
string name;
int ID;
};
inline int Student::GetID()
{
return ID;
}
You seem to be asking about operator< taking Students , however Student is not a class template, so the title of your post is baffling.
As someone else pointed out, your operator< is almost correct, except you have to actually call GetID() instead of comparing pointers to member functions.
This won't work yet until you fix GetID however. Instead of int Student::GetID(); it should be:
int GetID() const;
The const means that it can be called on objects passed by const reference, as you have in your operator< implementation. And you don't repeat the Student:: when declaring functions inside the class. (You use it when defining class members outside of the class definition).
Declare it as a friend function within your Student class, next to the rest of your member functions
friend bool operator < (Student& s1, Student& s2);
Your implementation is correct, it should go outside your Student class within the same header file.
Here's a template (queue) I'm trying to write:
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
template<class> class Node;
Node<T> *front;
Node<T> *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
void Push(const T& NewEl)
{
Node<T&> *El = new Node<T> (NewEl);
if (Empty())
front=back=El;
else
{
back-> next = El;
back = El;
}
}
void Pop()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
Node<T> *El = front;
front = front -> next;
delete El;
}
}
void Clear()
{
while (! Empty())
Pop();
}
};
template <typename T>
class Node
{
friend class Queue<T>;
public:
Node() {next = 0;}
Node(T nd) {nd=node; next=0;}
T& getsetnode(){return node;}
Node<T>*& getsetnext(){return next;}
private:
T front;
T back;
T node;
Node<T> *next;
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
queueInt->Back();
queueInt->Clear();
cout << "Clear" << endl;
return 0;
}
At these lines:
Node<T&> *El = new Node<T> (NewEl);
front = front -> next;
delete El;
I get Implicit instantiation of undefined template 'Queue<int>::Node<int>'. What am I doing wrong? After reading this post I tried changing int to const int to see if that was the problem, but apparently it isn't, because I get the same error.
I'm using XCode with LLVM compiler 4.2. When I switch to GCC I get more errors:
template<class> class Node; gets Declaration of 'struct Queue<int>::Node<int>',
Node<T&> *El = new Node<T> (NewEl); gets Invalid use of incomplete type,
and anything dealing with assignment of anything to El can't convert <int&>* to <int>* (but deleting reference doesn't change anything for LLVM).
template <typename T>
class Queue
{
private:
template<class> class Node;
/* ... */
This is a forward declaration of Queue::Node. The latter defined class Node is in the global namespace, so they aren't the same and any usage of Queue::Node will result in an incomplete-type error. Since you don't provide an interface to the interior nodes anyway just scrap the global definition of Node and stick it into Queue:
template <typename T>
class Queue
{
private:
class Node
{
public:
Node() {next = 0;}
/* ... */
};
/* ... */
};