I'm new to C++ and I keep getting this error message in the following class:
class LinkedList {
class Node *head;
class Node {
Student *student;
Node *next;
Node *prev;
public:
Node(Student *n_student, Node *n_next, Node *n_prev);
~Node();
Student *getStudent() const;
Node *getNext() const;
Node *getPrev() const;
};
public:
LinkedList();
~LinkedList();
void printList();
};
The method that causes the error:
void LinkedList::printList() {
using namespace std;
class Node *p_n;
p_n = head; // ERROR!
while (p_n) {
cout << '[' << (*(*p_n).getStudent()).getId() << ']' << endl;
p_n = (*p_n).getNext();
}
}
The error message I'm getting is
error: cannot convert 'Node*' to
'LinkedList::Node*' in assignment
I've tried casting Node to LinkedList::Node but I keep getting the same message. I'm compiling it in Xcode, not sure if that causes the problem.
Any idea how to fix this?
Change this:
class Node *head;
Into this:
Node *head;
When you declare a field of a certain class inside a class, you don't need the class keyword. Just the type name and its corresponding identifier. Like this:
Node *n;
LinkedList *l;
No class keyword. class keyword is only used when you actually declare/define a class.
Related
In c++ liked list Why we have to write node pointer like node* without specifying int, double etc. and we can also declare new node pointers in main without using any node class declaration.
class Node {
public:
int data;
Node* next;
};
If its any different kind of pointer then what it is called?
In your code
class Node {
public:
int data;
Node* next;
};
there is only one kind of node, and it has an int for data. That is why you don't need to write Node<int> or Node<double>. But you could change your code
template <typename T>
class Node {
public:
T data;
Node<T>* next;
};
This is called a template, and instead of only having an int for the data you can have any type. But now you have to say what that type is when you declare a variable. E.g.
Node<double>* ptr = new Node<double>();
I am trying to implement an AVL tree. Initially I implemented two classes, node and node_AVL as such:
class node{
protected:
int info;
node *l, *r;
public:
node *getRight();
};
class node_AVL : public node{
protected:
int height;
public:
void setHeight(int):
};
The problem arises when for example I try to access the child of a node:
node_AVL *node1 = node2.getRight();
Or
node_AVL node;
node.getRight().setHeight(1);
I get these errors:
Invalid conversion from node* to node_AVL*
Class node has no member setHeight()
How can I solve this?
As the error messages say, this line:
node_AVL *node1 = node2.getRight();
doesn't work because getRight() returns a node*. You could fix this by making node1 a node*, like this:
node *node1 = node2.getRight();
For the second part, you would need to do something like:
node node;
node.getRight()->setHeight(1);
This wouldn't work either since setHeight is a member of node_AVL.
You should maybe redesign your class, bearing in mind what you're trying to accomplish.
list.hpp
template <typename Data>
class List{
private:
struct Node* Head;
protected:
using LinearContainer<Data>::size;
struct Node
{
Data Elements;
Node* Nxt;
// Specific constructors
Node(Data);
};
public:
List() = default;
}
list.cpp
template<typename Data>
List<Data>::Node::Node(Data Elemento) {
List<Data>::Head.Elements = Elemento;
size = 1;
}
ERROR
error: invalid use of non-static data member 'Head'
List<Data>::Head.Elements = Elemento;
~~~~~~~~~~~~^~~~
1 error generated.
What’s my mistake, can you please tell me? I have not put the "main" as I know for certain that it has nothing to do while "size" is inherited from a higher class
First time caller here. I'm new to C++ and have tried for hours to figure this one out. Sorry to ask what seems a common question. I couldn't find the answer for the life of me.
I am getting the following compile error in visual studio:
error C2259: 'Node' : cannot instantiate abstract class
due to following members:
'void Node::printValue(void)' : is abstract.
It is my understanding that this means the pure virtual function that I created has not been implemented in a child class. From everything what I can see, it has been implemented in the intNode child. What am I doing wrong here? The code is below. Thanks in advance!
In Node.h:
class Node {
protected:
Node* nextNodePtr;
public:
Node();
Node* getNextNodePtr(void);
void setNextNodePtr(Node*);
~Node();
virtual void printValue() = 0;
};
class intNode : public Node {
int nodeInteger;
public:
virtual void printValue()
{
cout << "***" << endl;
}
intNode(int i)
{
nodeInteger = i;
}
};
In Node.cpp:
void intNode::printValue()
{
cout << "It's an int: " << nodeInteger << endl;
}
void Node::printValue()
{
cout << "This is just here fix compile error" << nodeInteger << endl;
}
Edit...sorry, I forgot to add this bit. The error is pointing to this section in main
int main()
{
Node* firstNode = new Node; <---- this line is where the error points
firstNode = new intNode;
intNode* intNode = new intNode;
You are not allowed to create instances of abstract classes. The message says so, you know it, so don't do it.
int main()
{
Node* firstNode; // do not create Node instance here.
// It's a compile time error and even if not,
// it would have been a memory leak.
firstNode = new intNode;
intNode* intNode = new intNode;
The following statement is incorrect.
It is my understanding that this means the pure virtual function that I created has not been implemented in a child class.
The error means that void Node::printValue(void) is pure virtual (i.e. void foo() = 0) in the Node class. This makes the Node class abstract. Since you cannot instantiate abstract classes, you see the error.
Additionally, as has been mentioned in the comments, you have defined void intNode::printValue() twice. That is incorrect.
I'm interested in doing something like the following to adhere to a Null Object design pattern and to avoid prolific NULL tests:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
Of course, as written, NullNode has different memory locations before and after the Node class declaration. You could do this without the forward declaration, if you didn't want to have default arguments (i.e., remove Node *r=NullNode).
Another option would use some inheritence: make a parent class (Node) with two children (NullNode and FullNode). Then the node example above would be the code for FullNode and the NullNode in the code above would be of type NullNode inheriting from Node. I hate solving simple problems by appeals to inheritence.
So, the question is: how do you apply Null Object patterns to recursive data structures (classes) with default arguments (which are instances of that same class!) in C++?
Use extern:
extern Node* NullNode;
...
Node* NullNode = new Node();
Better yet, make it a static member:
class Node {
public:
static Node* Null;
Node(Node *l=Null, Node *r=Null) : left(l), right(r) {};
private:
Node *left, *right;
};
Node* Node::Null = new Node();
That said, in both existing code, and amendments above, you leak an instance of Node. You could use auto_ptr, but that would be dangerous because of uncertain order of destruction of globals and statics (a destructor of some global may need Node::Null, and it may or may not be already gone by then).
I've actually implemented a recursive tree (for JSON, etc.) doing something like this. Basically, your base class becomes the "NULL" implementation, and its interface is the union of all interfaces for the derived. You then have derived classes that implement the pieces- "DataNode" implements data getters and setters, etc.
That way, you can program to the base class interface and save yourself A LOT of pain. You set up the base implementation to do all the boilerplate logic for you, e.g.
class Node {
public:
Node() {}
virtual ~Node() {}
virtual string OutputAsINI() const { return ""; }
};
class DataNode {
private:
string myName;
string myData;
public:
DataNode(const string& name, const string& val);
~DataNode() {}
string OutputAsINI() const { string out = myName + " = " + myData; return out; }
};
This way I don't have to test anything- I just blindly call "OutputAsINI()". Similar logic for your whole interface will make most of the null tests go away.
Invert the hierarchy. Put the null node at the base:
class Node {
public:
Node() {}
virtual void visit() const {}
};
Then specialize as needed:
template<typename T>
class DataNode : public Node {
public:
DataNode(T x, const Node* l=&Null, const Node* r=&Null)
: left(l), right(r), data(x) {}
virtual void visit() const {
left->visit();
std::cout << data << std::endl;
right->visit();
}
private:
const Node *left, *right;
T data;
static const Node Null;
};
template<typename T>
const Node DataNode<T>::Null = Node();
Sample usage:
int main()
{
DataNode<char> a('A', new DataNode<char>('B'),
new DataNode<char>('C'));
a.visit();
return 0;
}
Output:
$ ./node
B
A
C