Too few arguments inheritance c++ - c++

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 Listclass, but I want it to call the Unordered list's function get().

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.
[edit /]
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.

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.

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().

Related

How can I access member functions of STL classes inside derived classes that aren't in the base class? (detailed explanation in body)

Right now I have a base class, class Base{}, with two classes deriving from it, BFS{} and DFS{}. BFS has queue, and DFS has stack, so they both have a member called "nodes", but the type is their respective std::queue and std::stack. My search function takes in a pointer to base class as its parameter so that it can accept both derived classes, and runs the search by pushing and popping from the member classes inside the derived classes (as per the usual DFS BFS algorithms). The issue is, since I passed in my base class as the parameter, whenever I try to call push or pop on the member stack/queue called "nodes" from the derived classes, it always says that the push/pop cannot be done because there is no member inside the base class called "nodes". How am I supposed to make this work?
Also, this setup is a requirement of the assignment I am doing and I just can't figure out how this is supposed to work, any help is appreciated.
Thanks!
class Base {
public:
virtual void push(uint64_t roomID, float intensity, int distance) = 0;
virtual Node pop(void) = 0;
virtual int size(void) = 0;
};
class Breadth : public Base {
public:
std::queue<std::pair<uint64_t, int>> U;
void push(uint64_t roomID, float intensity, int distance) { std::pair<uint64_t, int> p(roomID, distance); U.push(p); }
Node pop() { Node rr; rr.ID = U.front().first; rr.distance = U.front().second; U.pop(); return rr; }
int size() { return U.size(); }
};
class Depth : public Base {
public:
std::stack<std::pair<uint64_t, int>> U;
void push(uint64_t roomID, float intensity, int distance) { std::pair<uint64_t, int> p(roomID, distance); U.push(p); }
UnexploredRoom pop() { U.pop(); }
int size() { U.size(); }
};
void robotSearch::searchLoop(Base* search, Discovered* D, uint64_t roomID)
{
Node room;
room.ID = roomID;
room.distance = 0;
search->U.push(room); //problem here, compiler wont let me push U
...
}
To implement custom behaviour through a pointer to a base class, you need to use virtual functions. Another approach would be to use generic code with templates.
Example:
class Base {
public:
virtual ~Base() {}
virtual void push(int i) = 0;
virtual int pop() = 0;
};
class DFS : public Base{
public:
virtual void push(int i) override { /*...*/ }
virtual int pop() override { /*...*/ return {}; }
};
class BFS : public Base {
public:
virtual void push(int i) override { /*...*/ }
virtual int pop() override { /*...*/ return {}; }
};
Right now, you have some virtual methods push and pop, but for some reason, you don't use them and instead try to access a member of the derived classes instead. You seem to have copied code from the answer by Ayjay but not applied it correctly.
That member U should really not be exposed like this, that is, it should be private, and you should use your class methods to manipulate it.
Therefore, you wouldn't write
search->U.push(room);
even if it was legal here (which it isn't, as the base class does not have anything named like that).
Instead, you go with
search->push(room);
Note that I omitted the other arguments that this takes, of course you also have to provide values for your intensity and distance arguments.
Doing so will call the appropriate method, that is either Breadth::push or Depth::push, which then will access the corresponding member of the respective class.
By the way, for reasons of control, you should use the override keyword as Ayjay did, and also, you should give a member a more descriptive name that U.

Can I force a class to be inherited?

Consider the following class:
//! Counter class base. Must be inherited.
class base_seeded_counter
{
public:
//! Destructor
virtual ~base_seeded_counter() { };
//! Get the next value.
int get_next();
protected:
//! Override the counter next value.
void set_next(const int next);
private:
int m_next_value; // Next value.
}
// ------------------------------------------------------
inline int base_seeded_counter::get_next()
{
return m_next_value++;
}
// ------------------------------------------------------
inline void base_seeded_counter::set_next(const int next)
{
m_next_value = next;
}
The purpose of this class is to implement a base counter object with the intention that it must be inherited. It does not have any virtual methods other than the destructor and, more importantly, does not initialize the m_next_value member. This is the job of the derived class. For example:
class file_seeded_counter : public base_seeded_counter
{
public:
file_seeded_counter(const std::string &file_name);
void reseed();
private:
std::string m_file_name;
}
inline int file_seeded_counter::file_seeded_counter(const std::string &file_name) :
m_file_name(file_name)
{
reseed();
}
inline void file_seeded_counter::reseed()
{
int seed_from_file;
// open file here and get seed value...
set_next(seed_from_file);
}
This class, deriving from base_seeded_counter reads the initial counter value from a file, and offers the ability to re-read the seed from the file via the reseed() method. There may be other classes that offer similar functionality to seed from databases, network sources, or a PRNG, for example.
My question is this: Given that I have no pure virtual methods, does C++ offer a mechanism to prevent someone from creating an instance of base_seeded_counter?
My question is this: Given that I have no pure virtual methods, does C++ offer a mechanism to prevent someone from creating an instance of base_seeded_counter?
Yes, give it a protected default constructor (may be empty).
Given that you already have a virtual destructor, the obvious way would be to declare it pure virtual. It's entirely legitimate to have a pure virtual destructor that's also defined in the base class:
class base_seeded_counter {
public:
virtual ~base_seeded_counter() = 0;
int get_next();
protected:
void set_next(const int next);
private:
int m_next_value;
}
inline virtual base_seeded_counter::~base_seeded_counter() {}
Defining the destructor this way doesn't change the fact that it's a pure virtual, so this class can't be instantiated.
As an aside, the comments you currently have in the code are 100% useless visual noise. A comment of get next on a function named get_next adds nothing useful at all.

C++ Template interface (list implementation)

I am trying to implement a list data structure in C++.
I want to define a list interface which would be later inherited by implementation such as ArrayList or LinkedList.
I'd like to be able to use it like
List<int>* testList = new LinkedList<int>;
So i've tried to implement full virtual templated class but then realized i cannot mix virtual and templated methods. I tried much different ways and im encountering problems all the way.
Whats the best way to do it ?
Edit (problematic code). I'm trying to make interface to look like this:
template<typename T>
class List {
public:
virtual void add(T*) {};
virtual void remove(unsigned int) = 0;
virtual unsigned int size() = 0;
virtual void get(unsigned int) = 0;
virtual ~List();
};
and then im trying to implement it here:
template<typename T>
class LinkedList : public List<T> {
/* some stuff */
public:
LinkedList();
virtual unsigned int size();
virtual void add(T*); // the problem i guess
virtual void remove(unsigned int);
virtual void get(unsigned int);
virtual ~LinkedList();
};
So i've tried to implement full virtual templated class but then
realized i cannot mix virtual and templated methods.
Your example code indicates, that you don't want virtual, templated methods, but a template class that has virtual methods. The former is not allowed, the latter IS (this is a common point of confusion).
So this is perfectly valid code:
#include <iostream>
#include <memory>
template<class T>
class List{
public:
virtual void push()=0;
virtual void pop()=0;
virtual ~List()=default;
};
template<class T>
class LinkedList: public List<T>{
public:
virtual void push() {
std::cout << "Pushed element to Linked List"<< std::endl;
}
virtual void pop() {
std::cout << "Poped element from Linked List"<< std::endl;
}
};
template<class T>
class ArrayList: public List<T>{
public:
virtual void push() {
std::cout << "Pushed element to ArrayList"<< std::endl;
}
virtual void pop() {
std::cout << "Poped element from ArrayList"<< std::endl;
}
};
int main()
{
List<int>* list1=new LinkedList<int>();
List<int>* list2=new ArrayList<int>();
// And this is how you would actually create objects on the heap nower days:
std::unique_ptr<List<int>> list3=std::make_unique<LinkedList<int>>();
list1->push();
list2->push();
list3->push();
list1->pop();
list2->pop();
list3->pop();
delete(list1);
delete(list2);
//no delete(list3) needed
return 0;
}
Besides that, I don't know, why you want to do that. C++ has a perfectly fine implementation of a linked list and an implementation of and array/vector and thanks to iterator based semantic, you can run (almost) any algorithm on them without the need for a common base class.
I apologize, if this sounds harsh, but it looks like you are comming from Java and trying to learn C++. But instead of learning C++, you try to write wrappers, that make C++ look like java. While this is certainly possible most of the time (as long as you don't forget, that standard c++ doesn't have a garbage collector) its often not a sensible approach. whether that holds true in your case of course depends on your application. But my recommendation ist to learn about iterators and the standard library algorithms.

What design pattern should I use to avoid dummy code here?

I have a base class -
class content
{
private:
int m_data;
public:
int getdbhandle() { return m_sql_db; }
void setData(int data) { m_data = data; }
virtual int getterrestrialServices { qDebug()"This is a dummy interface"; }
};
class telecontent: public content
{
virtual int getterrestrialServices { qDebug()" Real implementation here"; }
};
Now, the class content is instantiated as telecontent, when the product type is tele.
However, when the product type is generic - the dummy interface prints keep coming.
How can I avoid so? Is there any design pattern that forces the base class not to implement the dummy function? I want an efficient way so that only derived class has method. I don't want the base class to have that method. But, I can't modify the caller - code- so that the method is not called. I want the best way to strategically design such that the dummy interface can be avoided.
is there any design pattern that forces the base class not to
implement the dummy function?
Pure virtual allows this:
class content
{
private:
int m_data;
public:
virtual ~content() { }
int getdbhandle() { return m_sql_db; }
void setData(int data) { m_data = data; }
virtual int getterrestrialServices() = 0; // pure virtual
};
This means no one can create instances of content (will cause a compiler error), and so when some one inherits from content they must provide an implementation of getterrestrialServices() (else again, they'll get a compiler error).
What you need is pure virtual like so:
virtual int getterrestrialServices() = 0;
It will force every class the inherits content to implement it and you wont be able to create a content class, only classes the inherit from it so you wont have the dummy prints.

c++ handling derived class that's self referencing

So suppose I have a tree class like this in c++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.
But this specialNode* has member variables and functions that Node doesn't have.
I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.
Is there any clever, or just any better way to go about this?
Other than literally casting every time?
If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node
Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Now, it should work.
If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:
specialNode* var = static_cast<specialNode*>(children[i]);
Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}
If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.
You can actually do the following:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.
You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.