I'm trying to create a Node object using class Node:
int main(){
for(int i=0; i< 20; i++)
Node *handle = new Node(i, 10);
}
class Node{
public:
static vector<Node> map;
static int totalNodes;
vector<Node> connections;
int NodeID;
Node(int ID, int weight){
NodeID = ID;
CreateConnections(weight);
totalNodes++;
map.push_back(*this);
}
For some reason I get
'Node' : undeclared identifier
'Node' handle : undeclared identifier
syntax error : identifier node
Moving main() down after the class gives me
unresolved external symbol
for Node::map and Node::totalNodes
I'm somewhat new to C++ so any tips would be appreciated.
You have to end your class definition with ;
class Node
{
//....
map.push_back(*this);
}; //^^^Cannot miss ;
Meanwhile, you need to put declaration of Node before main.
Another point:
Node(int ID, int weight){
NodeID = ID;
CreateConnections(weight);
totalNodes++;
map.push_back(*this);
}//missing closing } on constructor definition
The reason that you have undefined reference to map and totalNodes is because:
static members of class must be initialized outside class. so when you inline constructor tries to access them, they are not defined. so you have undefined reference.
You should do something like the following:
class Node{
public:
static vector<Node> map;
static int totalNodes;
vector<Node> connections;
int NodeID;
Node(int ID);
};
int Node::totalNodes = 0; //definition of static variables
vector<Node> Node::map;
//^^^define constructor outside class body
Node::Node(int ID){ //your second parameter for ctor not used, so remove it
NodeID = ID;
totalNodes++;
map.push_back(*this);
}
You are declaring Node after its use. Just move the declaration before the main and you should be good:
class Node { ... };
int main() { ... }
You can also do a forward-declaration (declaration for the identifier without the definition) of the class:
class Node;
int main() { ... }
class Node { ... };
You either Need to do a Forward-declaration of Node like
class Node;
int main(){
for(int i=0; i< 20; i++)
Node *handle = new Node(i, 10);
}
class Node { }; //impelementation
or put main after defining class Node.
Just bung the following line for the first line:
class Node;
You need to put Node declaration prior to main where it is being used.
Just putting forward declaration is not enough as new Node in main requires Node to be declared.
As for the unresolved external, you need to define Node::totalNodes
int Node::totalNodes = 0;
Related
I need to access members of a linked list class inside of a linked list. I can manage my Artist list okay, but cannot set int x in my SongList class. I've tried setting it with *(temp->songHead).x = 5;, *temp->songHead.x = 5;, *(temp->songHead)->x = 5;, and *temp->songHead->x = 5;.
When I compile it, I get the error:
invalid use of incomplete type 'struct songList'
How can I set int x?
#ifndef LINKED_LIST
#define LINKED_LIST
class SongList{
public:
SongList();
int x;
void add(int x);
private:
struct Song{
char *name;
int minutes;
int seconds;
int views;
int likes;
Song *next;
};
Song *head;
};
class LinkedList{
public:
LinkedList();
~LinkedList();
void test(int x);
void add(char ch);
bool find(char ch);
bool del(char ch);
void list();
private:
struct Artist{
char character;
Artist *next;
struct songList *songHead;
SongList ptr;
};
Artist *head;
};
#endif
// Code to set int x
void LinkedList::test(int x){
struct Artist *temp;
temp = head;
*(temp->songHead).x = 5;
}
C++ doesn't require you to add struct in front of declarations of variables containing structs. Adding it allows you to use undefined types in your variable declarations.
If you remove struct you'll quickly see the true cause of your error:
songList *songHead;
Will give an error something like this (this is from clang, other compilers may not be as helpful):
error: unknown type name 'songList'; did you mean 'SongList'?
Your access to songHead is also incorrect:
*(temp->songHead).x = 5;
This is equivalent to:
*(temp->songHead.x) = 5;
What you actually want is:
(*temp->songHead).x = 5;
Or more simply:
temp->songHead->x = 5;
I'm confused why the following code cannot compile because of the following bug: 'rootLevel' was not declared in this scope.
In my understanding, the struct NodeLevel is declared and defined before class Solution, is this not a sufficient condition for this class to be available to the Solution class?
Thanks!
struct NodeLevel{
int level;
BinaryTreeNode * node;
NodeLevel(int val, BinaryTreeNode * x) : level(val), node(x) {}
};
class Solution {
public:
vector<vector<int>> levelOrder(BinaryTreeNode* root) {
queue<NodeLevel> q;
rootLevel = NodeLevel(0, root);
q.push(rootLevel);
/*
do some stuff with the queue
*/
}
};
The compiler is correct, you did not declare the variable rootLevel.
I have been solving a question, Dijkstra's Algorithm, in C++. I've implemented it using adjacency list.
So I have a class for a node, a class for a minHeap, and a class for the Graph.
class node
{
int vertex,weight;
node *next;
friend class Graph;
friend class minHeap;
public:
node();
node(int,int);
};
node::node(){
vertex=weight=0;
next=0;
}
node::node(int v,int wt){
vertex=v;
weight=wt;
next=0;
}
Do I define the minHeap class this way (without a friend function) and create an object in the getDijkSP() function normally, which allows me to use the object only in that function?
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap];
heapSize=-1;
pos=new int[cap]();
} //eliminating other methods
class Graph
{
node **adjList;
int v;
bool *visited;
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
}
void Graph::getDijkSP(){
minHeap hp(v); //here
hp.addElement(node(0,0));
for(int i=1;i<v;i++)
hp.addElement(node(i,INT_MAX));
while(!hp.isempty()){
node temp=hp.extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp.decreaseKey(current->vertex,current->weight+temp.weight);
}
}
(OR) Do I define the minHeap class with a friend function, so that I can create an object of the minHeap class using the new keyword? (And this helps me define the minHeap object in the scope of the Graph class, so that I can use it in all of its functions for other capabilities as well.)
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
friend class Graph; //say like this
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap]();
heapSize=-1;
pos=new int[cap]();
}
class Graph
{
node **adjList;
int v;
bool *visited;
minHeap *hp; //and do this
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
hp=new minHeap(v); //dynamic allocation
}
void Graph::getDijkSP(){
hp->addElement(node(0,0));
for(int i=1;i<v;i++)
hp->addElement(node(i,INT_MAX));
while(!hp->isempty()){
node temp=hp->extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp->decreaseKey(current->vertex,current->weight+temp.weight);
}
}
I have read this and a few other articles, but specifically want to know the advantages, disadvantages and the appropriateness of both the methods for such similar kinds of questions.
I've provided the constructors for the classes for better clarity.
Short answer would be NO. I would suggest you to read up on smart pointers and rewrite this whole mess. In C++ there is no real reason to use manual allocation in so simple project as this ever.
Also instead of assigning 0 or NULL to a pointer use nullptr, which is C++ symbol only for null pointers unlike the previous mentioned C values that are actually just a int 0 which may cause some unintentional errors.
Edit in response to your comment:
So I've decided to rewrite your code using actual modern C++ instead of this C code with simple classes. In your whole example there are almost no pointers or dynamic allocations needed. I wasn't absolutely sure who exactly should own the actual nodes so from the example I assumed that the MinHeap should. Also I didn't get the point of MinHeap::pos and Graph::visited from what I could see. I can explain any part of that code in more detail, just ask which.
Here is the code:
class Node {
// Only friend class required if you insist on keeping members of Node private.
// If they aren't meant to change, consider declaring them as public and const.
template <unsigned Size> friend class Graph;
public:
Node(int v, int wt) : vertex(v), weight(wt) {}
private:
// Default values written in here right after declarations
// There is no need for a default constructor. You never call it anyway.
int vertex;
int weight;
Node* next = nullptr;
};
// Template parameter because of internal use of std::array.
// If the capacity shouldn't be constant, use std::vector and remove template.
template <unsigned Capacity>
class MinHeap {
public:
// No constructor needed
// ---------------------
// One small tip: write parameter names in function declarations
// even if they aren't needed there for better readability of your code.
void addElement(Node n) { /* impl */ }
Node extractMin() { /* impl */ }
unsigned capacity() { return Capacity; }
bool isEmpty() { return heap.isEmpty(); }
private:
// Default values written in here right after declarations
int heapSize = -1;
std::array<Node, Capacity> heap;
};
// Template parameter because of internal use of std::array.
// If the vertex count shouldn't be constant, use std::vector and remove template.
template <unsigned Vertices>
class Graph {
public:
// No constructor needed
// ---------------------
void getDjikSP() {
hp.addElement({0, 0});
for (unsigned i = 1; i < hp.capacity(); ++i)
hp.addElement({0, INT_MAX});
while (!hp.isEmpty()) {
Node tmp = hp.extractMin();
std::cout << tmp.vertex << " " << tmp.weight << std::endl;
for (Node* current = adjList[tmp.vertex]; current != nullptr; current = current->next)
hp.decreaseKey(current->vertex, current->weight + tmp.weight);
}
}
private:
// Default values written in here right after declarations
std::array<Node*, Vertices> adjList;
MinHeap<Vertices> hp;
};
There is still a lot of space for improvements of this code, for example the MinHeaP::extractMin should maybe return Node&& if it is removed from the heap or const Node& if it should return a reference to the top, etc. To address all the problems and inefficiencies this can still have I would need to see the full code with all functions.
I have the following class declaration (I've tried to remove as much excess code as possible):
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int) {
return new Node;
}
};
This gives no error. However, as soon as I define the function "findNode" outside of the class, I get an error; here's the code:
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int);
};
Node * List::findNode(unsigned int index) {
return new Node;
}
Now, when running the code, I get an error saying "LinkedList.cpp:9:1: error: 'Node' does not name a type".
I would appreciate any help in determining the problem.
Until the compiler encounters List:: it has no idea the Node you're talking about is a member of List. Change the definition to:
List::Node * List::findNode(unsigned int index) {
return new Node;
}
The "naked" Node inside the function is fine because by that time the compiler knows the function is a member of List.
I'm coming from a Python background, so forgive me on this one. Though I will provide the Python equivalent of what I'm looking for.
I'm creating a list of network nodes, so I wanted to create a class, "Node", that stores their MAC, IP address, and Hostnames, along with a function that prints them out prettily. The following is my code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Node {
string MAC, IP, Hostname;
public:
void set_values(string M, string I, string H);
string list() {return "MAC: "+MAC+"\nIP: "+IP+"\nHostname: "+Hostname+"\n";}
};
void Node::set_values(string M, string I, string H) {
MAC = M;
IP = I;
Hostname = H;
}
int main(int argc, char* argv[])
{
Node firstnode;
firstnode.set_values("C0:FF:EE:C0:FF:EE","192.168.1.60","My-PC");
cout<<firstnode.list();
}
Which prints this out when I run it:
MAC: C0:FF:EE:C0:FF:EE
IP: 192.168.1.60
Hostname: My-PC
What I want is to have these objects automatically added to a vector called NodeList upon creation. For example, here is how I did that in Python:
RecordersList=[]
class Recorder:
def __init__(self, ARecorder, BRecorder, CRecorder):
self.ARecorder = ARecorder
self.BRecorder = BRecorder
self.CRecorder = CRecorder
RecordersList.append(self)
I tried a similar move, where I put the line:
vector<Node> NodeList; before the class declaration (and NodeList.push_back(this); as a Public function), and tried after the class declaration, but either way the compiler isn't aware of the Node class by the time the vector is declared, or vice versa the Node class isn't aware of the NodeList vector.
Is there a way to do this? It would be self-referencial class appending to an existing vector whose type is of that class.
Sure: declare and define a static member in the class, push the this pointer onto it:
class Foo; // forward declaration to make vector happy
class Foo {
private:
static std::vector<Foo *> store;
public:
Foo() { store.push_back(this); }
};
std::vector<Foo *> Foo::store;
Do it explicitly:
std::map<std::string, Node> map;
map[mac1] = Node(mac1,...);
map[mac2] = Node(mac2,...);
In my experience, this sort of design will often not end well due to having to manually manage memory in C++. this is a raw pointer to the object and it is not managed.
You can do this:
class Node; // forward declaration
std::vector<Node*> NodeList;
class Node
{
public:
Node()
{
NodeList.push_back(this); // pass a POINTER to this object
}
};
int main(int argc, char* argv[])
{
Node* node1 = new Node(); // allocated a Node
Node* node2 = new Node(); // allocated a Node
// ...
// deallocate ALL nodes
std::vector<Node*>::iterator it = NodeList.begin();
while (it != NodeList.end())
{
delete *it;
++it;
}
NodeList.clear();
}
The problem with this solution is if you have pointers pointing to indivual nodes. You could end up with dangling pointers and memory corruption.
And alternative solution is:
class Node
{
public:
Node();
};
std::vector<Node> NodeList;
Node::Node()
{
NodeList.push_back(*this); // pass a REFERENCE to this object
}
int main(int argc, char* argv[])
{
Node node1; // create a node
Node node2; // create a node
// ...
}
The problem with this alternative design is that each node passed to NodeList will be a new COPY of that node. So if you do:
int main(int argc, char* argv[])
{
Node node1; // NodeList[0] is logically equal to node1
node1.DoStuffThatModifiesTheContent();
// At this point, node1 is no longer a logical equivalent of NodeList[0]
}
A better design would involve creating a NodeManager class of some sort, and creating and accessing nodes through this manager, which would control the lifetime of all the node objects.