Create a MultiClass Queue C++ - c++

Is possible create a queue for differents types of Objects, but with same interface?
As example, I have an interface called SensorItem, and 4 kinds of Class, SensorItemA
,SensorItemB,
SensorItemC
,SensorItemD
`
queue <SensorItem> cola;
void encolar(SensorItem* dato)
{
cola.push (*dato);
}
SensorItem* sacar()
{
SensorItem* d=cola.front();
cola.pop();
return d;
}
Thats my class Queue(Cola)
and here i try to use it
void main()
{
Cola c=new Cola();
TemperatureItem t=new TemperatureItem(3.25);
c.encolar(t);
ImuItem i=new ImuItem(3,4,8);
}
its something wrong in my syntax? or just is not possible to do it?

Polymorphism in C++ only works with references and pointers. Objects in C++ are objects, not references. If you create a SensorItem it will always be a SensorItem, not a TemperatureItem or a ImuItem. If you have a std::queue<SensorItem>, it's elements will always be SensorItems, never TemperatureItems or ImuItems.
If you want to make a queue of objects derived from SensorItem, you need to use a queue of pointers to SensorItems:
#include <iostream>
#include <queue>
#include <memory>
struct SensorItem
{
virtual void doAThing() = 0;
virtual ~SensorItem() {}
};
struct TemperatureItem : SensorItem
{
void doAThing() { std::cout << "TemperatureItem\n"; }
};
struct ImuItem : SensorItem
{
void doAThing() { std::cout << "ImuItem\n"; }
};
class Cola
{
private:
std::queue<std::unique_ptr<SensorItem>> cola;
public:
void encolar(std::unique_ptr<SensorItem> dato)
{
cola.push(std::move(dato));
}
std::unique_ptr<SensorItem> sacar()
{
std::unique_ptr<SensorItem> d = std::move(cola.front());
cola.pop();
return d;
}
};
int main()
{
Cola c;
c.encolar(std::make_unique<TemperatureItem>());
c.encolar(std::make_unique<ImuItem>());
std::unique_ptr<SensorItem> item = c.sacar();
item->doAThing();
item = c.sacar();
item->doAThing();
}
Live on Coliru
Here I've used std::unique_ptr to avoid having to do manual memory management. You could use raw SensorItem*s, but I would advise against it.

Related

"Default delete" errors when trying to use unique_ptr with vectors for polymorphism in C++

I'm relatively new to C++, and I'm hoping someone can help me resolve an issue I'm having with unique_ptr and vectors. Essentially I'm trying to use polymorphism so that I have a vector of type "Base", which is an abstract class (pure virtual). I'm then attempting to fill this vector with derived classes. I've included a trivial example below, showcasing exactly what I'm trying to achieve. Please note that I need to use C++11, which is why I haven't made use of "std::make_unique".
The code compiles fine, but I get run-time errors about "default_delete" in class Animal.
A related question is should I be using unique_ptrs for run-time polymorphism as below? Or should I be using raw pointers instead?
Header file and CPP files below. Error output from VS is included below this. Very many thanks in advance for any help with this.
HEADER FILE:
#ifndef START_H
#define START_H
#include <vector>
#include <memory>
class Animal
{
public:
virtual ~Animal() = default;
void run();
void setNumLegs(int a) { numLegs = a; }
const int getLegs() const { return numLegs; }
private:
double numLegs;
virtual void useLegs() = 0;
};
class Biped : public Animal
{
private:
void useLegs();
};
class Multiped : public Animal
{
public:
double costOfShoes{ 12.0 };
private:
void useLegs();
void payForShoes();
void becomeDestitute();
};
class Farm
{
public:
std::vector<std::unique_ptr<Animal>> animals;
};
class Countryside
{
public:
std::vector<std::unique_ptr<Farm>> farms;
};
#endif // START_H
CPP FILE:
#include "start.h"
#include <iostream>
int main() {
Countryside countryside;
std::unique_ptr<Farm> f(new Farm);
std::vector<int> legs = { 2,4,5,2,10 };
for (auto& numLegs : legs) {
if (numLegs == 2) {
std::unique_ptr<Biped> biped(new Biped);
biped->setNumLegs(numLegs);
f->animals.push_back(std::move(biped));
}
else if (numLegs > 2) {
std::unique_ptr<Multiped> multiped(new Multiped);
multiped->setNumLegs(numLegs);
f->animals.push_back(std::move(multiped));
}
}
countryside.farms.push_back(std::move(f)); //THIS IS WHERE THE PROBLEM IS I THINK
for (auto& animal : f->animals) {
animal-> run();
}
return 0;
}
void Animal::run()
{
useLegs();
}
void Biped::useLegs()
{
std::cout << "Running with: "<< getLegs() <<"legs\n";
}
void Multiped::useLegs()
{
std::cout << "Running with many legs:" << getLegs() << "!!! legs\n";
payForShoes();
}
void Multiped::payForShoes()
{
std::cout << "Paying for shoes...\n";
becomeDestitute();
}
void Multiped::becomeDestitute()
{
std::cout << "I have no money left.\n";
}
DEBUGGER ERROR OUTPUT:
_Mypair <struct at NULL> std::_Compressed_pair<std::allocator<std::unique_ptr<Animal,std::default_delete<Animal>>>,std::_Vector_val<std::_Simple_types<std::unique_ptr<Animal,std::default_delete<Animal>>>>,1>
_Mypair._Myval2 <struct at NULL> std::_Vector_val<std::_Simple_types<std::unique_ptr<Animal,std::default_delete<Animal>>>>
this 0x00000000 <NULL> std::vector<std::unique_ptr<Animal,std::default_delete<Animal>>,std::allocator<std::unique_ptr<Animal,std::default_delete<Animal>>>> *
Hi the problem is you are deferencing a null pointer in the for loop (f is set to nullptr).
The move operation moves the ownership of the item pointed to and the pointer f is set to nullptr (move semantics)
After a move the object can no longer be used

constructor inside a method c++

I have a constructor inside a method that I want to have access at all time
//ItemEditor.cpp
#include "ItemContainer.h"
void ItemEditor::CreateItem() {
ItemContainer* wornItems = new ItemContainer();
}
inside of my driver I call my method createItem();
//driver
int main(){
ItemEditor* createItem = new ItemEditor();
createItem->CreateItem();
}
afterwards I want to have access to backpack outside of the createItem
How can I accomplish that?
Make the item container a member variable so its scope is the life time of the object.
There is no reason to use dynamic allocation, so just use an instance of the ItemContainer instead of a pointer.
#include <iostream>
class ItemContainer {
int item = 0;
public:
void addItem(int i) {
item = i;
}
int getItem() {
return item;
}
};
class ItemEditor {
public:
ItemEditor() {
}
void createEditor() {
wornItems.addItem(3);
}
ItemContainer wornItems;
};
int main() {
ItemEditor editor;
int item = editor.wornItems.getItem(); //or some method
std::cout << item << std::endl;
editor.createEditor();
item = editor.wornItems.getItem(); //or some method
std::cout << item;
return 0;
}
You can also make the container private and use public methods to access its contents. You can see an example here
By backpack I assume whatever is returned by
createItem->CreateItem();
Why not just store it in a pointer since you used the new to allocate the object in a heap?
ItemContainer* ItemEditor::CreateItem() {
return new ItemContainer();
}
Main file:
int main(){
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
}
Also I want to suggest it is a better practice to provide a move semantic for ItemContainer and get rid of pointers. That way you are relying on RAII and stack for object destruction, less risk of memory-leak. Related article:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
Here is a full compiling code:
//Header.h
#include <iostream>
class ItemContainer{
public:
void sayHello(){
std::cout << "HulloWorld!\n";
}
};
class ItemEditor{
public:
ItemEditor(){};
ItemContainer* ItemEditor::CreateItem(){
return new ItemContainer();
}
};
MainFile:
//main
#include "Header.h"
int main()
{
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
backpack->sayHello();
}

C++ array of object constructors

I have several classes named Child1, Child2 ... etc, inherited from object Parent. I need to create an object by its name, for example if I have string "Child1", I need to create object Child1 and so on.
I thought about something like:
struct registry_entry {
const char* name;
IREGISTRY* (*initializer)();
};
struct registry_entry registry_list[] =
{
{"xml", &REGISTRY_XML::REGISTRY_XML},
}
But I can't get address of object constructor.I believe that this problem must be already solved, and the solution is pretty simple, but I can't find it.
Constructors and destructors are special functions and cannot be accessed through function pointers.
You need to create a static member function like
struct REGISTRY_XML {
static IREGISTRY* create();
};
thus you can refer to it as
struct registry_entry registry_list[] =
{
{"xml", &REGISTRY_XML::create},
}
Your code looks very C-like and not very C++-like, but if you can actually use the full power of C++11, I would go with a combination of std::function, lambdas, std::unique_ptr and std::map.
Lambdas can wrap constructors without you having to write separate wrapper functions, std::function allows you to store the lambdas in a map, std::unique_ptr eliminates many memory-management bugs, and std::map performs the actual mapping from strings to initialiser functions.
Here is a complete example:
#include <functional>
#include <string>
#include <memory>
#include <map>
#include <iostream>
struct IREGISTRY {
virtual ~IREGISTRY() {}
virtual void print() = 0;
};
struct REGISTRY_XML : IREGISTRY { void print() override { std::cout << "XML\n"; } };
struct REGISTRY_INI : IREGISTRY { void print() override { std::cout << "INI\n"; } };
struct REGISTRY_JSON : IREGISTRY { void print() override { std::cout << "JSON\n"; } };
int main()
{
std::map<std::string, std::function<std::unique_ptr<IREGISTRY>()>> const registry_list = {
{ "xml", []() { return std::make_unique<REGISTRY_XML>(); } },
{ "ini", []() { return std::make_unique<REGISTRY_INI>(); } },
{ "json", []() { return std::make_unique<REGISTRY_JSON>(); } },
};
auto const initializer_iter = registry_list.find("xml");
if (initializer_iter != registry_list.end())
{
auto const initializer = initializer_iter->second;
auto const registry_ptr = initializer();
registry_ptr->print();
}
}

How to get rid of weak_ptrs in a container

I have a class that stores weak_ptrs in a container and later does something if the weak_ptr is not expired:
class Example
{
public:
void fill(std::shared_ptr<int> thing)
{
member.push_back(thing);
}
void dosomething() const
{
for (const auto& i : member)
if (!i.expired())
;// do something. the weak_ptr will not be locked
}
private:
std::vector<std::weak_ptr<int>> member;
};
If Example is an object that lives forever and fill is used regularily, the vector allocates memory for elements continously, but they are never removed after they expired.
Is there any automatic C++ way to get rid of the expired weak_ptrs in the container or is there a better way to store a variable number of them?
My naive way would be to iterate over the container each time fill is called and remove all the expired weak_ptrs. In scenarios where Example has many elements in the container and fill is frequently called this seems to be very inefficient.
Since you clarified that you are actually using a std::map and not a std::vector, it might be easiest to remove the expired elements on-the-fly in doSomething(). Switch back from a range-based for loop to a normal iterator based design:
void dosomething() const
{
auto i = member.begin();
while( i != member.end() ) {
if( i->expired() ) { i = member.erase( i ); continue; }
;// do something. the weak_ptr will not be locked
++i;
}
}
Does the shared_ptr<int> have to be a shared_ptr<int>?
How about a shared_ptr<IntWrapper>?
#include <iostream>
#include <forward_list>
using namespace std;
class IntWrapper {
public:
int i;
static forward_list<IntWrapper*>& all() {
static forward_list<IntWrapper*> intWrappers;
return intWrappers;
}
IntWrapper(int i) : i(i) {
all().push_front(this);
}
~IntWrapper() {
all().remove(this);
}
};
void DoSomething() {
for(auto iw : IntWrapper::all()) {
cout << iw->i << endl;
}
}
int main(int argc, char *argv[]) {
shared_ptr<IntWrapper> a = make_shared<IntWrapper>(1);
shared_ptr<IntWrapper> b = make_shared<IntWrapper>(2);
shared_ptr<IntWrapper> c = make_shared<IntWrapper>(3);
DoSomething();
return 0;
}
I would rather use a custom deleter for the shared_ptr. But this implies here to change the interface of the Example class. The advantage using custom deleter is that there is no need to check for expired objects in the collection. The collection is directly maintained by the custom deleter.
Quick implementation :
#include <memory>
#include <iostream>
#include <set>
template <typename Container>
// requires Container to be an associative container type with key type
// a raw pointer type
class Deleter {
Container* c;
public:
Deleter(Container& c) : c(&c) {}
using key_type = typename Container::key_type;
void operator()(key_type ptr) {
c->erase(ptr);
delete ptr;
}
};
class Example {
public:
// cannot change the custom deleter of an existing shared_ptr
// so i changed the interface here to take a unique_ptr instead
std::shared_ptr<int> fill(std::unique_ptr<int> thing) {
std::shared_ptr<int> managed_thing(thing.release(), Deleter<containter_type>(member));
member.insert(managed_thing.get());
return managed_thing;
}
void dosomething() const {
// we don't need to check for expired pointers
for (const auto & i : member)
std::cout << *i << ", ";
std::cout << std::endl;
}
using containter_type = std::set<int*>;
private:
containter_type member;
};
int main()
{
Example example;
auto one = example.fill(std::unique_ptr<int>(new int(1)));
auto two = example.fill(std::unique_ptr<int>(new int(2)));
auto three = example.fill(std::unique_ptr<int>(new int(3)));
example.dosomething();
three.reset();
example.dosomething();
}

Storing functors in a stl map and calling them

I am trying to store functors in a stl map and then call it one by one , but now sure how to call it. This is what I have tried so far.
#include <iostream>
#include <map>
#include <string>
class BaseFunctor {
public:
BaseFunctor() {
}
~BaseFunctor() {
}
};
template <typename T>
class MyFunctor : public BaseFunctor {
public:
T operator()(T x) {
return x * 2;
}
};
int main ( int argc, char**argv ) {
std::map<std::string, BaseFunctor*> m_functorMap;
m_functorMap.insert(std::make_pair("int", new MyFunctor<int>()));
m_functorMap.insert(std::make_pair("double", new MyFunctor<double>()));
m_functorMap.insert(std::make_pair("float", new MyFunctor<float>()));
m_functorMap.insert(std::make_pair("long", new MyFunctor<long>()));
for ( std::map<std::string, BaseFunctor*>::iterator itr = m_functorMap.begin(); itr != m_functorMap.end(); ++itr ) {
std::cout << *(itr->second)() << std::endl;
}
return 0;
}
I cannot use boost
You have a map full of BaseFunctor*, but BaseFunctor is not callable since it has no operator(). You cannot call without casting to a pointer of a derived type, preferably with dynamic_cast. Overall it doesn't look like a good design. You are attempting to use run-time polymorphism where it can't.