Reputation: 39
I'm working on learning inheritance by making a generic List
class. List
can be an Unordered
list, an Ordered
list, a Stack
, or a Queue
.
My List
class looks like this:
class List
{
public:
class Node
{
public:
int data;
Node * next;
Node(int data);
};
int sizeOfList = 0;
Node * head = nullptr;
List::List();
virtual void get(int pos);
virtual void insert(int data);
virtual void remove(int pos);
virtual void list();
virtual int size();
};
My Unordered
list class looks like this:
class UnOrderedList : public List
{
public:
UnOrderedList();
void get();
void insert(int data);
virtual void remove(); //takes no parameters because first item is always removed
};
In main()
, I create an array of Lists like this;
List * lists[8];
and make an Unordered list like this:
lists[0] = new UnOrderedList();
My question:
lists[listNum]->get();
gives error
"too few arguments in function call"
because it thinks I am trying to call get()
in the List
class, but I want it to call the Unordered list's function get()
.
Upvotes: 0
Views: 206
Reputation: 1262
I feel I must improve upon Sam Varshachik's answer - though he is totally correct.
class List
{
public:
virtual void get(int pos);
};
class UnOrderedList : public List
{
public:
void get();
};
Note that there are two problems here - not just one.
Firstly the signature of get(int)
is different from get()
- these are two different methods, and the compiler will treat them as such.
Further you have declared that the method List::get(int)
be virtual, but you have not done-so for UnOrderedList::get()
- Remember that the list
object has no knowledge about it's children - Thus a list *
cannot understand the details of UnOrderedList
.
Consider this example:
class List
{
public:
virtual void get(int pos);
};
class UnOrderedList : public List
{
public:
virtual void get(); //STILL AN ERROR!
};
In this case, I have made UnOrderedList::get()
virtual - However this won't help. As list still has no knowledge of this method.
The correct snippet is as follows:
class List
{
public:
virtual void get(int pos);
virtual void get();
};
class UnOrderedList : public List
{
public:
virtual void get(); //We can use this now!
virtual void get(int pos); //This is only needed if we intend to override this method
};
In this example list::get()
is now a virtual method - as such any call to it will be communicated to the correct-child as you intended.
This is only possible however because the parent class has been informed that such a method exists, and can be over-ridden by the child classes.
As JonathanPotter stated in the comments, pay attention to the fact that the virtual keyword is only needed if you wish for a method called from a parent-pointer to be routed to the actual child object. And that this does incur some overhead.
Upvotes: 2
Reputation: 37192
lists[0]
is a List*
as far as the compiler's concerned.
UnOrderedList::get()
won't override List::get(int pos)
because the signatures are different. If you want the derived class to override a function in the base class the function signatures have to be the same.
As it is, you would need to cast lists[listNum]
to UnOrderedList*
to call UnOrderedList::get()
, e.g. static_cast<UnOrderedList*>(lists[listNum])->get()
.
Upvotes: 1
Reputation: 118445
You need declare get()
as a virtual method in the List
class. Either that, or dynamic_cast
it.
When you invoke get()
using a pointer to a List
, that particular pointer can point to any subclass of List
. Just because one particular subclass of List
implements a particular method doesn't mean that you can invoke it directly using a pointer to the base class.
Otherwise, there's no point to have base classes. And this is exactly what virtual methods are for: to allow you to invoke the methods in a subclass, using a pointer to the base class.
Upvotes: 2