Cannot instantiate abstract class, but I have - c++

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.

Related

Calling parent function from another function using child C++

So I have a parent Class which is:
class Node
{
public:
Node();
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node);
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
And a child inheriting from that class:
class Cube : public Node
{
public:
Cube();
};
Now I have another file which has a function that uses the child class:
#include "cube.h"
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube c;
mainCube.addChildNode(c);
}
}
Problem is that mainCube doesn't see the addChildNode function which the parent has. What is the point of inheriting from another class if the parents functions aren't accessible from another place using the child class?
No, the parent classes public functions are callable from the child object.
However, the prototype of the function is
void Node::addChildNode(Node node);
So it's taking a Node object & not a Cube object.
So your compiler cannot find a function which takes a Cube object & hence the error.
The fix is to use a pointer to Node or reference to Node while declaring/defining the function.
So you function should be
void addChildNode(Node & node);
In which case, the Node object can be passed to the function & the compiler will find it.
Even better would be to have
// if you aren't looking to modify the passed object inside addChildNode
void addChildNode(const Node & node);
The following is fine & hence the function will work
Cube b;
Node &a = b;
or
Node * pn = &b;
The derived classes should be able to see the addChildNode function if you keep the signature of the function aligns. This is not a big issue. However, there are a few more "serious" issues with your code:
You need to make the base class' destructor virtual to avoid some undefined behaviors.
You have to design the ownership of nodes carefully. I guess you want the Node class to own and manage its children nodes. That means function addChildNode actually takes the ownership of the passed in node object, and it should also be deleted during destruction.
In function addCubes(), there is a loop that keeps calling addChildNode function but passes the local variable Cube c; which will be out of scope and destroyed after the loop. Thus, the parent object mainCube will holds pointers to already destroyed objects, and it will cause a crash.
After fixing all these issues, your code looks like this:
class Node
{
public:
Node() {};
virtual ~Node() {
for(auto n: childNodes) delete n;
};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node*> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node) {
childNodes.push_back(node);
};
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
class Cube : public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube *c = new Cube();
mainCube.addChildNode(c);
}
}
It is preferred to use smart pointers to manage memory, and the code is more elegant and easier to read, and it makes it harder to make mistakes :-).
#include <memory>
class Node
{
public:
Node() {};
virtual ~Node() {};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<std::shared_ptr<Node>>& getChildNodes(){return this->childNodes;}
void addChildNode(std::shared_ptr<Node> node) {
childNodes.push_back(std::move(node));
};
void removeNode();
private:
// childNodes own elements in it, they will be deleted automatically.
std::vector<std::shared_ptr<Node>> childNodes;
Node* parentNode = nullptr;
};
class Cube: public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
auto c = std::make_unique<Cube>();
mainCube.addChildNode(std::move(c));
}
}
Assuming that you have shared the entire implementation of your code. You have not defined the body of the function addChildNode, similar to setParentNode etc. You need to do something like childNodes.push_back(node); inside that function.
Note: It is also necessary that you pass the input to addChildNode as shown in the answer by #user93353. Also, define childNodes as std::vector<Node *> in order to avoid object slicing.

Creating a class with attributes of this class type + inheritance to other class (Node classs and NodeAVL)

I'm trying to do the following code:
class Node
{
protected:
int *value;
Node *leftChild;
Node *rightChild;
friend class BST;
public:
Node(int value = 0);
virtual ~Node();
virtual int info();
};
Node::Node(int value) : leftChild(nullptr), rightChild(nullptr) {
this->value = new int(value);
std::cout << "Creating the node " << *(this->value) << "\n";
}
class NodeAVL : public Node
{
private:
friend class AVL;
public:
int *balanceFactor;
NodeAVL(int value = 0);
virtual ~NodeAVL();
};
NodeAVL::NodeAVL(int value) : Node(value) {
this->balanceFactor = new int(0);
std::cout << "Creating the AVL node " << *(this->value) << " with balance factor " << *(this->balanceFactor) << "\n";
}
Now, my problem is that I should derive NodeAVL (mandatory), and I have a problem with the Node class (base class), because there are declarations of Node *leftChild and Node *rightChild, and when I create an AVL node, it creates its children of type Node*. How can I create it with the type NodeAVL*?
Or how can I create a class T like:
class T{
T* leftChild;
T* rightChild;
}
so that I would have Node class have Node children and NodeAVL which is derived from Node have NodeAVL children?
Since you have tagged your post with polymorphism I will give you a runtime polymorphism based answer. You don't.
Part of the point of runtime polymorphism is that an object dervied from the base class can be passed and stored as an object of the base class while still retaining its overriden functionality (Yes slicing is an issue but we are dealing with pointers here). Therefore you do not need Node to be changed to NodeAVL, simply setting leftChild or rightChild to point at an object of NodeAVL instead of Node is enough, any overriden methods will call the method in NodeAVL.
You are setting your nodes to nullptr anyway but if you didn't then you could make a Node contructor which takes pointers for leftChild and rightChild (possibly make it protected so only derived classes can use it).
As a side note use your initaliser list to set value instead of setting it afterwards. Also prefer smart pointers to naked pointers.

Program should fail/crash while dynamic_cast is working

In my opinion following program should be crashed but its not only working but showing the right result("derv is called").
#include <iostream>
using namespace std;
class base
{
public:
virtual ~base(){}
};
class derv: public base
{
public:
void f() { cout << "derv is called" <<endl;}
};
int main() {
base* p = new base();
derv *d1 = dynamic_cast<derv*>(p);
// Since p point to base , so d1 should return nullptr
//calling any function using d1, should fail/crash
//but why the following line is working ??
d1->f();
}
Sorry I forgot to add few lines in my previous post: If I add a single data member and try to access it, gives me segmentation fault, which I think is the correct behavior. My Question is that why accessing data member changes the behavior ? When variable is not get accessed , calling "f()" function is successful while the same function "f()" gives segmentation fault when accessing with the data member? Is it the undefined behavior?
class derv: public base
{
public:
int x = 0 ; // Added new member, c++11
void f() { cout << "derv is called " << x << endl;} //access it here
};
It is undefined behavior in your program you dereferencing d1 which is a NULL pointer:
base* p = new base();
derv *d1 = nullptr;
d1 = dynamic_cast<derv*>(p);
if(nullptr == d1) // condition succeeds which means d1 is nullptr
cout << "nullptr" << endl;
A safe programming is the task of the programmer not the compiler's so a good program checks before uses:
// avoiding error prones and UBs
if(nullptr != d1)
d1->f();
f is not a virtual function. The program does not have to look for the virtual function table when trying to call f, so the method is called anyway.
If you try to check the pointer value of this inside of f, it will be nullptr.

C++ array of the same class hierarchy

According to my book, if I want to make an array of objects that are not in the same class but in the same class hierarchy, I need to use pointers:
class text
{
public:
void write(string text);
void show();
private:
string texte;
};
void text::write(string text)
{
texte = text;
}
void text::show()
{
cout << texte;
}
class text_with_stars : public text
{
public:
void show();
};
void text_with_stars::show()
{
cout << "*";
text::show();
cout << "*";
}
int main()
{
text* array[2];
array[0] = new text;
array[0]->write("Hello");
text_with_stars* pointer = new text_with_stars;
pointer->write("Hi");
array[1] = pointer;
for (int i=0;i<2;i++)
{
array[i]->show();
}
return 0;
}
But when I do this, the output is "HelloHi" meaning that the second object used the show version that is from text and not from text_with_stars, but I made it exactly the same way that the book described. What Is the problem??
Here is what is written in the book:
Question* quiz[2];
quiz[0] = new Question;
quiz[0]->set_text("Who was the inventor of C++?");
quiz[0]->set_answer("Bjarne Stroustrup");
ChoiceQuestion* cq_pointer = new ChoiceQuestion;
cq_pointer->set_text("In which country was the inventor of C++ born?")
cq_pointer->add_choice("Australia",false);
...
quiz[1] = cq_pointer;
The chapter right next to the one I was reading is about virtual functions and it explains that the system will always use the member functions of Question instead of ChoiceQuestion, looks like I should read more before asking questions on internet!
void show()
needs to be virtual in the base class if you want to use methods from derived classes from base class pointers
The reason this is happening is because the function you are calling is non-virtual.
Let's say we have a class Parent and a class Child inheriting from the parent:
class Parent {
public:
void f() {
cout << "Parent::f()" << endl;
}
};
class Child : public Parent {
public:
void f() {
cout << "Child::f()" << endl;
}
};
Now, let's make a pointer to a Parent and store a Child in it (polymorphism):
Parent *ptr = new Child;
ptr->f();
At this point, the compiler sees ptr having type Parent* and determines that the function to be called is Parent::f().
In order to call Child::f() when dealing with polymorphism? The Parent::f() must be defined virtual. The compiler then generates code to check at run-time the value that is stored in memory to call the appropriate (child) function.
In short: ONLY when a function is virtual and is called on a pointer or reference, a memory lookup is made to determine the actual type at that point in memory. Otherwise it is not.

C++ nested class error "cannot convert ... in assignment"

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.