I'm creating a new class that inherits queue from the STL library. The only addition to the class is a vector. This vector will have the same size of the queue and it will store some integer values that will correspond to each objects in the queue.
Now, I want to override pop() and push(), but I simply want to add more functionality to the parent's class methods.
ex. When pop() is called on the queue object, I also want pop an object from the vector. When push() is called on the queue object, I also want insert a new object into the vector.
How do I do that???
#include <iostream>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
template <typename type>
class CPU_Q : public queue<type>
{
public:
vector<int> CPU_TIME;
void increaseTime()
{
for(int ndx = 0; ndx < CPU_TIME.size(); ndx++)
{
CPU_TIME[ndx]++;
}
}
void push(type insertMe)
{
//This is what I want to do
super::push(); // or queue::push(); maybe?
CPU_TIME.push_back(0);
}
void pop()
{
//Something very similar to push()
}
}
Many Many thanks in advance
-Tri
You asked about:
void push(type insertMe){
//This is what I want to do
super::push(); // or queue::push(); maybe?
CPU_TIME.push_back(0);
}
That would be more like:
void push(type insertMe) {
queue<type>::push(insertMe);
CPU_TIME.push_back(0);
}
Except you probably want to accept the parameter by const reference:
void push(type const &insertme) {
queue<type>::push(insertMe);
CPU_TIME.push_back(0);
}
That said, the standard container classes aren't really designed for inheritance (e.g. they don't have a virtual dtors), so you'll have to be careful with this -- e.g. when you destroy it, you'll need the static type to be the derived type; you'll get undefined behavior if (for example) you destroy one via a pointer to the base class.
STL queue class in not intended to be extended using inheritance. Look here for more information on that. Besides that std::queue has more than one template argument. Instead of inheriting you could just use std::queue as a member of your template class CPU_Q as follows:
template<typename T>
class CPU_Q
{
std::queue<T> q;
public:
void push( T val )
{
q.push( val );
// additional work
}
};
Simple answer is that it is not possible. STL container classes are not designed to be inherited. Their destructor is not virtual to start. If you really want to do something like this then write a new class which 'contains' the queue and vector , and use this class everywhere. BTW as a side note, there is no super keyword in C++ unlike Java. If you want to call base class method use BaseClassName::methodName();
Unless your new class has a is-a relationship with std::queue, I would strongly consider encapsulating the queue and vector, and providing methods that forward to the appropriate std::queue/std::vector methods, in the order you want them to be called.
Also, if you want this new class to be compatible with standard algorithms, you will have to implement a begin() and end() method that return an iterator type capable of walking your data structure; you may be able to use the existing methods on std::queue/std::vector to accomplish this though.
Related
I am trying to write a program that searches for a node in a tree, starting from a root-node. As I want the search-algorithm to be as generic as possible, I want to use templates, and I want to use SFINAE to check if a given type implements all the functions I need.
To calculate the successors of a node, the type of the node has to have the function successors(), which returns a vector of nodes:
#include <vector>
class has_successors_t {
public:
virtual std::vector<has_successors_t> successors() = 0;
};
the class to do the search looks like this:
#include <type_traits>
template <class node_t,
class = std::enable_if_t<std::is_base_of<has_successors_t, node_t>::value>>
class breadthFirstSearch {
public:
static node_t search(node_t root_node) {
// search for the target node
}
};
That way I tried to make the program compile only if a given type has a function to calculate its successors. But when I try to do the following:
#include <vector>
class some_node_t : public has_successors_t {
public:
std::vector<some_node_t> successors() {
// return the successors
}
};
I get an error: error: invalid covariant return type for 'virtual std::vector<some_node_t> some_node_t::successors()'.
So, I know what the error means, but how can I solve problems like this? I could imagine that I am not the first one to encounter problems where I have a base class and a derived class, and I want an overwritten function in the derived class that returns a vector (or array, or queue, or anything like that) which contains elements of the derived class. But I just can't find a solution for that.
Thanks in advance for any help!
Greetings,
Sebastian
You are breaking the basic rule of thumb. Run time olymorhism aka OOP in C++ only works with pointers or references. If you don't have
pointers or references, there is no polymorphism and you don't need virtual functions or even base classes at all. You can SFINAE out on successor method directly rather than on a base class.
Something like this should fit the bill.
template <class N,
class = enable_if_t<is_same_v<vector<N*>,
decltype(declval<N>().successors())>>> ...
The following assumes you will have pointers (smart or otherwise) because juggling nodes by value might not be an attractive proposition. I will use regular pointers for brevity
You might be able to achieve something like that with CRTP.
template <typename S>
class has_successors_t {
public:
virtual
std::vector<S *> successors() = 0;
};
class some_node_t : public has_successors_t<some_node_t> {
public:
std::vector<some_node_t *>
successors() {
// return the successors
}
};
Then the search function becomes just
template <class node_t>
class breadthFirstSearch {
public:
static node_t
search(has_successors_t<tnode_t> * root_node) {
// search for the target node
}
};
This however means that you will need to deal with has_successors_t<some_node_t> * rather than just has_successors_t *. Which leads to the next question. If you already have has_successors_t<some_node_t> *, why not just go one step further and have just some_node_t * and ditch has_successors_t altogether. Oops! We're back to SFINAEing out on having successors, only with pointers this time.
There are some uses for CRTP but you need to see for yourself whether it fits your design.
I am trying to implement a Priority Queue using a Vector template in C++. I am most comfortable with Java and want to mimic the idea of an Interface, where all objects that can use the Priority Queue are required to implement certain methods.
I know that C++ does not support Interfaces, however, someone suggested that by tapping into Multiple Inheritance this could be achieved by creating an Abstract Class and requiring some virtual functions.
I would like all objects that can use the Priority Queue to implement:
public:
int compareTo(Comparable &obj);
Here is a C++ Abstract Class that achieves this:
Comparable.h
class Comparable {
public:
Comparable();
~Comparable();
virtual int compareTo(Comparable &obj) = 0;
};
This works great, no errors are formed from supplying the Abstract Class to the Vector template:
vector<Comparable> *mElements = new vector<Comparable>(); // no error
It is not until I try to use polymorphism in a class that inherits from the Comparable class that I run into an issue. Because the Method signature receives a Comparable&, I am having trouble accessing the members of the class that extends Comparable:
int Event::compareTo(Comparable& obj) {
// Min-Heap - time of currentObject is less than e.mTime
Event e = (Event) obj; // Doesn't work - No C-style cast (can I make one and how?)
// if I trying obj.mTime, this won't work because it is not a member of the Comparable class
if (mTime < e.mTime) return Delta::NEGATIVE_CHANGE;
if (mTime > e.mTime) return Delta::POSITIVE_CHANGE;
return return Delta::NO_CHANGE;
}
All I need to do is compare the time in this example, but I would like to design the class so that clients only have to inherit from the Comparable class and implement the one method for use of the priority queue.
Thanks for any help in advanced!
You are searching for dinamic_cast
http://en.cppreference.com/w/cpp/language/dynamic_cast
dinamic_cast has a ugly name cause you shouldn't use it too much. In this case, you don't need it.
First, in C++ you can overload operators (<, >, ==...). If these operators doesn't exist, the class can't be compared. It's more natural and easy for compare :)
Second, you can use a generic template:
template<class T>
class Comparable {
public:
Comparable();
~Comparable();
virtual int compareTo(T &obj) = 0;
};
class event : public Comparable<event> {
//...
public:
int compareTo(event &e) override;
};
You can detect wrong types in compile time, you don't need cast in execution time :)
override is one c++11 flag for compiler: "This function should override one parent function, check it". You can remove it freely if you don't use C++11
Actually, you don't need the Comparable class at all, if the PriorityQueue class is a template itself. It will compile for types that implement compareTo and won't compile for types that don't implement it.
template <class T>
class PriorityQueue {
...
void someMethod(const T& obj) {
if (someOtherObj.compareTo(obj)) {
...
}
}
...
}
As I previously said in a comment, the STL ordered containers use functors instead of requiring some specific interface for their elements. Easier than using a functor is using < to compare objects:
if (someOtherObj < obj) {
That Comparable class actually fits the ideia of a concept (C++14), not an abstract interface. It helps to clarify for a template class/function what is its required interface, but concepts are a very new feature of the C++ language and not widely supported or even known.
I have a class Bar which stores objects derived from BarItem:
#include <list>
#include <memory>
class Bar {
public:
typedef std::shared_ptr<BarItem> item_ptr;
void add_item(item_ptr item) {
items_.push_back(item);
}
private:
std::list<item_ptr> items_;
};
I have another class Note which is a subclass of BarItem. Currently to add a copy of a Note object I am doing:
Bar my_bar;
Note my_note;
my_bar.add_item(Bar::item_ptr(new Note(my_note)));
Which is a bit ugly; I would like to know if there is a better way or a way to automate this?
You can't actually avoid the copy (in C++11 you can make it a move), but you can "automate" it so you save a few keystrokes by overloading the add_item function for each type (that may be child of BarItem).
template <class T>
typedef enable_if<is_base_of<BarItem, T>::value,void>::type add_item(const T& item) { /* or T&& */
items_.push_back(item_ptr(new T(item)));
}
You can move that ugly part in the function itself as:
template<typename ItemType>
void add_item(ItemType item) //change the signature
{
items_.push_back(new ItemType(item)); //add the copy!
}
and call it as:
my_bar.add_item(my_note);
Using pointers in containers is one way of reducing the copying of objects. But the way you're handling the creation of the Note object involves making a copy of it via the copy constructor!
Can you avoid having an object and instead have a pointer to the object? You could do this by putting the creation inside a function (factory). That function will take the constructor's arguments, new the object and return a smart pointer.
What I have:
Vectors of different custom structs(one custom struct per vector)
I used pointers to each struct to give it a static size per record
A vector that combines these vectors via a pointer to each
When I try to cast a pointer to the custom vector it fails on every iteration
My workaround is a call to a function that takes the vector pointer as an argument and returns a void pointer.
I know this is wrong despite being functional, but I can't find a reference on the right way to define the cast method properly.
I'm looking for the right way to accomplish this.
typedef struct mystruct {
DWORD something;
vectorclassa * somethinga;
vectorclassb * somethingb;
};
typedef std::vector<mystruct*> amystruct;
void * theWrongWay(mystruct * apointer){
return apointer;
}
typedef std::vector bigvector;
If I try to bigvector.push_back(&instance_of_amystruct)
It fails. If I change std::vector<amystruct*> bigvector to a void* and call theWrongWay with a &amystruct instance, it compiles/runs. It just seems wrong.
The problem is that I don't know how to define the missing method for vector or cast it to something vector knows how to deal with without doing something...bad.
It's very hard to answer this question because it's hard to tell why you want to do this. Why do you want to keep vectors of different types in another vector?
Anyway, I'll just assume that you want to do this because there's some common action you want to take on each vector. Then you can simply define an abstract class that defines that action, and have a templated child class of this class that keep a different vector depending on the template argument. You can then keep the vectors in a container referring to them as their common ancestor. Some code:
class ActionableVector {
virtual void doSuperCoolStuff() = 0;
}
template<typename T>
class VectorHandler: public ActionableVector {
vector<T> handledVector;
// vector<T> & handleVector; // You can keep a reference to an external vector too
virtual void doSuperCoolStuff() {
//do super cool stuff in a type-safe manner
}
}
template<>
class VectorHandler<ATypeThatNeedsSpecialAttention>: public ActionableVector {
Vector<ATypeThatNeedsSpecialAttention> handledVector;
virtual void doSuperCoolStuff() {
// Do especially cool stuff
}
vector<ActionableVector*> myVectors;
for(ActionableVector * av: myVectors ) { //C++ 11 yaay
av->doSuperCoolStuff();
}
If you really really really want to keep objects of completely different types in a container, and willing to sell your soul to the devil for that, look at this answer.
Are there any suggestions on how to use a nested class iterator
in an ABC in C++ ? Note that, I also want to have a virtual function returning an
instance of this class.
More specifically here's my approach:
class ABC {
typedef iterator<forward_iterator_tag, MyType> MyTypeIter;
virtual MyTypeIter *begin() = 0;
};
class Foo : ABC {
MyTypeIter : public ABC::MyTypeIter;
virtual MyTypeIter *begin();
};
ABC::MyTypeIter *Foo::begin()
{
Foo::MyTypeIter *ret;
ret = new Foo::MyTypeIter(...);
return ret;
}
Is there a better approach than this (e.g. one that does not use pointers) ?
What is your problem? A nested class behaves the same way as a top-level class, so you may return its objects just as you would have returned any other.
Take a look on how iterators are implemented for std::vector class, for example.
I prefer to keep iterators interal to the class and exposing only an interface for iteration.
For example, you can implement a List<> with the methods:
void prepare_iteration() // reset the internal iterator
bool step_iteration() // move internal iterator
DATA_TYPE & read() // return the data by using the iterator
write( DATA_TYPE & ) // update the data by using the iterator
In this example the iterator can be a simple node pointer and it's never exposed to the user.
I find this approach much easier and safer than iterator objects.(well the 'safer' part needs a lot of discussion)
The above interface can be implemented as an abstract class.
Your container (or whatever) classes can inherit it and implement it.
I know that's not the answer that you are looking for but it's just an alternative idea to design your classes.