Vector of shared pointers updates existing elements on push_back - c++

Basically, I have a vector of shared_ptr as member data to a class.
This vector is populated by calling a member function from another class function.
Problem new elements added to the vector updates values of existing elements.
The setup is as follows:
class A
/*
* Class A has a header with class declarations and a distinct implementation.
* For the sake of brevity, the relevant information is shown in this snippet.
*/
class A {
public:
A(std::string name) : m_name(name);
std::string& get_name();
private:
std::string m_name;
}
typedef std::shared_ptr<A> A_ptr;
class B
/*
* Class B has a header with class declarations and a distinct implementation.
* For the sake of brevity, the relevant information is shown in this snippet.
*/
class B {
public:
void add_element(A_ptr& element) {
/*
this is where the problem is:
i DO get the proper element (i can verify this by calling the get_name() method on `element`).
Assume we got in succession:
- ONE
- TWO
- THREE
...
*/
std::cout << element -> get_name << std::endl;
m_elements.push_back(element);
/*
...
fast forward here, when I print the content of the vector held in this class,
the old elements added have been updated somehow and I get this:
- when we get ONE, the vector contains: [ONE]
- when we get TWO on the next call to this function, the vector contains: [TWO, TWO]. I expect [ONE,TWO]
- when we get THREE on the next call to this function, the vector contains: [THREE, THREE, THREE]. I expect [ONE, TWO, THREE]
-> WHAT ON EARTH IS GOING ON HERE?
*/
for (auto it = m_elements.begin(); it != m_elements.end(); ++it)
std::cout << (* it) -> get_name() << std::endl;
}
private:
std::vector<A_ptr> m_elements;
}
typedef std::shared_ptr<B> B_ptr;
class B is the problem class. In the add_element() function, I am getting the proper elements to add (namely ONE, TWO and THREE).
But, after the push_back(), not only the new element is added, the existing elements all have their values updated to the new element that got added.
So say I add elements with names ONE then TWO, instead of getting a vector with elements as [ONE, TWO], I get [TWO, TWO].
class C
/*
* Class C has a header with class declarations and a distinct implementation.
* For the sake of brevity, the relevant information is shown in this snippet.
*/
class C {
public:
void do_something() {
std::string name = name_obtained_dynamically();
B_ptr manager(new B());
do {
A_ptr element_one(nullptr);
A_ptr element_two(nullptr);
if (we_are_good) {
element_one.reset(new A(name));
}
else {
element_two.reset(new A(name));
}
if (element_one !=nullptr)
manager -> add_element(element_one);
else
manager -> add_element(element_two);
} while(condition_is_true);
}
}
class C calls add_element() from class B and keeps adding elements to said vector.
So far as I can tell, the problem probably lies with my use of shared pointers inside that loop.
But what exactly I am doing wrong, I cannot tell.

Related

How can I create a vector that holds three different types of vectors

I have three structs (Foo, Bar, Fruit) and I want a vector to hold each struct like vector<Foo> Foo_holder; vector<Bar> Bar_holder; vector<Fruit> Fruit holder; and then I want to try and put all three of those vectors into one vector. So it should end up like this with Vector_holder being the top level vector that I wish to know how to create:
Vector_holder
--- Foo_Holder
------Instance of Foo
--- Bar_holder
------Instance of Bar
--- Fruit_holder
------Instance of Fruit
How do I go about doing this?
The possible duplicate question lists a problem that the vectors must be the same size or the code breaks, and the vectors in my question will be shifting size a whole lot. I also feel this would help beginner C++ learners more than the other question.
The solution I found here works for me and is overall alot simpler than the nearly essay long answer. I'm more of a beginner in C++ and as such appreciate the easier to understand answer here.
Whenever such a grouping makes sense, I tend to put it into a struct and hence name it. In this case,
struct FooBarFruitHolder {
std::vector<Foo> foos;
std::vector<Bar> bars;
std::vector<Fruit> fruits;
};
which you can then use as
std::vector<FooBarFruitHolder> vec;
vec.emplace_back();
and e.g. fill it with objects:
/* Add a Foo element to all FooBarFruitHolder instances. */
for (auto&& fooBarFruitHolder : vec)
fooBarFruitHolder.foos.emplace_back(/* Arguments passed to Foo ctor */);
The naming is essential here, so choose what fits best in your application. Initialization might also be easier to read when you pass parts of this nested datastructure into functions which setup the member variables, e.g.
void initialize(std::vector<Foo>& foos)
{
foos.emplace_back(/* Arguments for first Foo object */);
foos.emplace_back(/* Arguments for second Foo object */);
}
initialize(vec.front().foos);
vector to hold each struct like vector Foo_holder; vector
Bar_holder; vector Fruit holder; and then I want to try and put
all three of those vectors into one vector.
One way to interpret your (somewhat ambiguous) statement is that you also want a single vector that holds all N element types in it. (But I suspect you will like lubgr's answer better.)
For this the third vector, I suggest you consider Polymorphism.
If you derive each of your structs from an interface class, perhaps
class FooBarFruit_t
{
//...
virtual void whistle() = 0;
virtual void bounce() = 0;
virtual void f1() = 0;
virtual void f2() = 0;
virtual void f3() = 0;
virtual void reflect();
//...
}
then you can easily create a vector where any of the N types can be loaded
std::vector<FooBarFruit_t*> holder;
The next challenge will be to create virtual methods that each derived class can support.
a) They may be abstract, f1(), f2() ...
b) They may be very specific, such as whistle(), which is something that only foo can do (and bars and fruit would take no action on being commanded to whistle()).
[I'm not sure what kind of behavior these typically in-animate instances might take, but software is where abstraction really helps.]
What this buys you is, at run time, you do not have to know what kind of FooBarFruit_t you are commanding to action.
By invoking f3(), each instance (foo or bar or fruit) will do what what you ask, and each f3() simply fulfills the expectation you have for that type.
If the instance does not reflect(), you can either implement a method that a) does nothing, or b) invokes FooBarFruit_t::reflect(). Or several other options.
Consider that you might want to display all objects:
for (auto fbf : holder) fbf->show();
for (auto fbf : holder) fbf->diagnostic(); // or diagnostic
for (auto fbf : holder) fbf->reset(); // or reset
Any reason these need to be considered different?
There should not be a place where you feel the need to do something specific based on type:
void something() {
for (auto fbf : holder) {
switch(fbf.type())
{ // vvvvv - enumeration of types
case Foo: foosomething(); break;
case Fruit: fruitsomething(); break;
case Bar: barsomething(); break;
default : assert(0); break;
}
}
}
But no one will stop you from doing so you think you must.
You could use Boost's zip iterator to "zip together" the different vectors:
vector<Foo> Foo_holder;
vector<Bar> Bar_holder;
vector<Fruit> Fruit holder;
/* ... insert elements etc. */
auto start = boost::make_zip_iterator(
std::make_tuple(ia.begin(), d.begin(), ib.begin())
);
auto end = boost::make_zip_iterator(
std::make_tuple(ia.end(), d.end(), ib.end())
);
Now, this doesn't result in a vector, just a pair of iterators. But now you can use them with STL algoritms. For example:
std::for_each(start, end, [](auto a_foo, auto a_bar, auto a_fruit) {
std::cout << "The Foo element is " << foo << "\n";
std::cout << "The Bar element is " << bar << "\n";
std::cout << "The Fruit element is " << fruit << "\n";
}
and you can also use these iterators to create a single range object. This is described, for example, in this answer by #leemes to a related question of mine.

C++ How to pass a vector of pointers (double pointers) as a constant to a function

I have a class A in C++ with many attributes:
class A{
public:
B** tab;// B is another class or structure
....
void compute();//this function does calculations on elements inside tab
};
In a third class C, there is a function that uses the tab variable as input, reads each element and does some calculations to write results on another attribute of the class C:
C::compute(B** tab){
....// I need that **tab be protected inside this function and its elements does not change
}
How can I make tab: the vector of pointers protected (or constant) ?
One possible way is something like this:
C::compute(B * const * tab){
// nothing in this array of pointers will be changed
tab[0] = (B *) 0x3254; // compile error as desired
}
Or you can ban changing even pointer to pointers like this:
C::compute(B * const * const tab){
// nothing in this array of pointers will be changed
tab = (B * const *) 0x3254; // compile error
}
If you need to protect only pointers in array the first example is your choice
How about using vector:
class A {
vector<vector<B> > tab;
//...
}
C::compute(const vector<vector<B> >& tab) {
// tab, tab[0] and tab[0][0] are all const
}

C++ Object-oriented programming

I have 1 question because I am pretty curious how to handle with such problem.
I have base class called "Pracownik" (Worker) and 2 subclasses which are made from public Pracownik;
- Informatyk (Informatic)
- Księgowy (Accountant)
Writing classes is easy. Made them pretty fast but I have small problem with main because I am helping friend with program but I was not using C++ for a while. So:
This is my header file "funkcje.h"
#include <iostream>
using namespace std;
class Pracownik
{
private:
string nazwisko;
int pensja;
public:
Pracownik(string="",int=0);
~Pracownik();
string getNazwisko();
int getPensja();
friend double srednia_pensja(int,Pracownik);
};
class Informatyk : public Pracownik
{
private:
string certyfikat_Cisco;
string certyfikat_Microsoft;
public:
Informatyk(string="",int=0, string="", string="");
~Informatyk();
void info();
};
class Ksiegowy : public Pracownik
{
private:
bool audytor;
public:
Ksiegowy(string="",int=0, bool=false);
~Ksiegowy();
void info();
};
double srednia_pensja(int,Pracownik);
These are definitions of my functions "funkcje.cpp"
#include "funkcje.h"
Pracownik::Pracownik(string a,int b)
{
nazwisko=a;
pensja=b;
}
Pracownik::~Pracownik()
{
}
string Pracownik::getNazwisko()
{
return nazwisko;
}
int Pracownik::getPensja()
{
return pensja;
}
Informatyk::Informatyk(string a, int b, string c, string d) : Pracownik(a,b)
{
certyfikat_Cisco=c;
certyfikat_Microsoft=d;
}
Informatyk::~Informatyk()
{
}
Ksiegowy::Ksiegowy(string a, int b, bool c) : Pracownik(a,b)
{
audytor=c;
}
Ksiegowy::~Ksiegowy()
{
}
void Informatyk::info()
{
cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
cout<<"Certyfikat Cisco: "<<certyfikat_Cisco<<endl;
cout<<"Certyfikat Microsoft: "<<certyfikat_Microsoft<<endl;
}
void Ksiegowy::info()
{
cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
cout<<"Audytor: ";
if(audytor)
cout<<"Tak"<<endl;
else
cout<<"Nie"<<endl;
}
double srednia_pensja(int a,Pracownik *b)
{
return 0;
}
And finally main!
#include <iostream>
#include "funkcje.h"
using namespace std;
int main()
{
Pracownik lista[10];
Pracownik *lista_wsk = new Pracownik[10];
Informatyk a("Kowalski1",1000,"Cisco1","Microsoft1");
Informatyk b("Kowalski2",2000,"Cisco2","Microsoft2");
Informatyk c("Kowalski3",3000,"Cisco3","Microsoft3");
Ksiegowy d("Kowalski4",4000,1);
Ksiegowy e("Kowalski5",5000,0);
lista[0]=a;
lista[1]=b;
lista[2]=c;
lista[3]=d;
lista[4]=e;
Informatyk *ab = new Informatyk("Kowalski1",1000,"Cisco1","Microsoft1");
Informatyk *ac = new Informatyk("Kowalski2",2000,"Cisco2","Microsoft2");
Informatyk *ad = new Informatyk("Kowalski3",3000,"Cisco3","Microsoft3");
Ksiegowy *ae = new Ksiegowy("Kowalski4",3000,1);
Ksiegowy *af = new Ksiegowy("Kowalski5",3000,0);
lista_wsk[0]=*ab;
lista_wsk[1]=*ac;
lista_wsk[2]=*ad;
lista_wsk[3]=*ae;
lista_wsk[4]=*af;
for(int i;i<5;i++)
{
lista[i].info();
cout<<endl;
}
cout<<endl;
// for(int i;i<5;i++)
// {
// lista_wsk[i].info();
// }
return 0;
}
Ok and here goes my questions:
I had to create array which is filled with base class objects "Pracownik".
Secondary i had to create array which is full of pointers to class "Pracownik" objects.
(Hope those 2 first steps are done correctly)
Next thing I had to write to array 3 objects of class Informatic and 2 of class Accountant.
So I ve created 5 objects manually and added them into the array in such way array[0]=a;. I guess this is still good.
Next thing i had to create and add similar objects to array of pointers using new. So I ve created array with new and pointers to objects with new. (Hope thats correct 2).
And FINALLY:
I had to use info() on added to array objects.
This is my main question if my array is type "Pracownik" and I want to use function info() from subclasses how should I do that? And how compiler will know if he should use info() from Accountant or Informatic while I am trying to show those information using "for".
In an array of Pracownik, the elements are of type Pracownik. Any information about the objects being of a subclass of Pracownik are lost when you copy the elements into the array.
This is called object slicing and leads to the fact that there is no way to invoke Informatyk::info() on these objects.
If you want to call methods of a subclass, you have to prevent object slicing by storing pointers or references in the array.
As Oswald says in his answer,
Pracownik * lista_wsk = new Pracownik[10];
allocates an array of 10 Pracownik objects. This is probably not what you want. With polymorphism involved, we usually want to deal with pointers or references. Hence, you'd want an array of Pracownik * pointers. Since you already know at compile-time that it will have 10 members, there is no need for a dynamic allocation here. I think you've meant to write
Pracownik * lista_wsk[10];
instead. Now we don't put objects but pointers to objects into the array. For example:
lista_wsk[2] = new Informatyk("Kowalski3", 3000, "Cisco3", "Microsoft3");
And then we can iterate over the items like so:
for (unsigned i = 0; i < 10; ++i)
std::cout << lista_wsk[i]->getNazwisko() << std::endl;
As you have already discovered, it is impossible to call a subclass function member on a superclass object. It would be possible to figure out the actual type at run-time yourslf by means of a cast.
for (unsigned i = 0; i < 10; ++i)
if (Informatyk * info_ptr = dynamic_cast<Informatyk *>(lista_wsk[i]))
info_ptr->info();
dynamic_cast returns a pointer to the target class if this is possible or a nullptr (which evaluates to false, hence the conditional) otherwise. Note however that this is considered very poor style. It is better to use virtual functions. Therefore, add
virtual void
info()
{
// Do what is appropriate to do for a plain Pracownik.
// Maybe leave this function empty.
}
to the superclass and again to the subclass
virtual void
info() // override
{
// Do what is appropriate to do for an Informatyk.
}
The function in the subclass with the same signature is said to override the function inherited from the superclass. Since the function is marked as virtual, the compiler will generate additional code to figure out at run-time what version of the function to call.
If you are coding C++11, you can make the override explicit by placing the keyword override after its type as shown above (uncomment the override). I recommend you use this to avoid bugs that arise from accidental misspelling or other typos.

Perform some operation on each of recursive structure's element, without adding methods to it in C++

The task: perform operation on each of recursive structure's element, without modifying it (the structure has only members and no methods except for constructor) inside Presenter::present(...) method (that makes use of private members of Presenter).
The problem: the structure does NOT have any methods except for constructor.
Example:
I have an structure:
struct Component{
std::vector<Component *> children;
Component * parent;
std::string ID;
std::string content;
Component(ID, content){...}
};
Then I have some code like:
Component * a, * b, * c1, * c2;
a = new Component("A", "a content");
b = new Component("B", "b content");
c1 = new Component("C1", "c1 content");
c2 = new Component("C2", "c2 content");
b->parent = a;
a->children.push_back(b);
c1->parent = b;
c2->parent = b;
b->children.push_back(c1);
b->children.push_back(c2);
I now want, having a pointer passed to my Presenter::present(...):
class Presenter{
private:
std::string somethingImportant; // = "sth";
...
public:
std::string present(Component * a){
... //on each component's children (and component itself):
//get ID and content then add something from this (Presenter)
//or modify the ID/content a bit.
//At the end, return the result (for all components together).
}
...
}
Output to std::string (or console, nvm) all ID-content pairs like:
A a content sth
B b content sth
C1 c1 content sth
C2 c2 content sth
It could be easily achieved by adding some recursivePresent(std::string &output) method to Component structure.
But I want to know if it's possible to do it without modifying Component structure (without adding any method to it)?
EDIT (made because of comments): Note that the output makes use of some Presenter's private/protected members/methods - I cannot assume that it will be just one "sth" like in an example.
I cannot find such solution, but I believe that somebody here can surprise me with some crazy idea ;)
Answer to comment: #firda can you explain it a bit? I'm not sure what do you mean.
My comment was: Why not having it (the recursivePresent helper) on Presenter?
class Presenter {
void presentRecursive(Component *c, std::ostream& out) {
out << c->ID << ' ' << c->content << std::endl;
for(auto p : c->children) presentRecursive(p, out);
}
public:
void present(Component *c) {
presentRecursive(c, std::cout);
}
};
At runtime, a C++ struct (or class) object does not know its structure, fields, layout or size. These are only known at compilation time.
If you add a new field long newfield; at the end of your struct Component, most routines in your code will stay the same (except those allocating such a structure, they are using its size).
You need to have some runtime meta-data describing the structure of your object.

Program design with polymorphism and differing data structures

I think I have a design issue here and I would really appreciate your help.
I have a class Base representing a basic algorithm.
class BaseAlgo: public Algo<double>
{
public:
/// data structures
// ...
//
struct Item {
double profit;
double weight;
double xjSolution;
};
typedef std::pair<double, std::vector<Item>::iterator> ScaledItem;
protected:
std::vector<Item> & items_;
boost::ptr_vector<ScaledItem> largeItems_;
}
The BaseAlgo has some functions, some of them virtual, others not.
As a derived class I have
class DerivedAlgo: public BaseAlgo
{
public:
/// enhanced data structures
// ...
//
struct DerivedScaledItem : ScaledItem {
int additional;
};
}
In my virtual functions which I overload in DerivedAlgo, I need access to the additional parameter of DerivedScaledItem which is not quite the original intent of polymorphism. Is it somehow possible or do you propose a different design approach? I am open to anything at the moment as I am completely stuck.
Right now, the largeItems_ member ptr_vector in BaseAlgo holds ScaledItems (internally as pointers). I thought, I could use this somehow like this:
// in DerivedAlgo
void someMethod(std::vector<Item>::iterator someiterator){
DerivedScaledItem doubledItem = {};
doubledItem.first = 4.5;
doubledItem.second = someiterator;
doubledItem.additional= 2;
largeItems_.push_back(new UnboundedScaledItem(doubledItem));
boost::ptr_vector<DerivedScaledItem>::iterator it = largeItems_.begin();
std::cout << "added large item " << *it << std::endl;
}
When I cout the just added object, additional is set to 2. But after that, calling the getter for largeItems_, the additional field will be set back to 0, only the two fields which are known in ScaledItem are then set.
// in BaseAlgo
const boost::ptr_vector<ScaledItem>& getLargeItems() const
{
return largeItems_;
}
// from my test.cpp
DerivedAlgo obj;
// ... define someiterator
obj.someMethod(someiterator);
boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();
boost::ptr_vector<DerivedAlgo::DerivedScaledItem>::iterator it = largeItems.begin();
std::cout << "read large item " << *it << std::endl;
I guess you didn't tell boost how to clone your ptr_vector-s elements, like described here:
http://www.boost.org/doc/libs/1_54_0/libs/ptr_container/doc/tutorial.html#cloneability
So in this line, where you create a copy of the vector (you could avoid this by declaring largeItems as a reference), they get copied via the constructor of ScaledItem, which looses your additional member.
boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();
Regarding your question about another design:
You could pass the type of the vectors elements as a template parameter to the base class.
You could move the vector into the derived class, and provide only (virtual, abstract) functions to access single elements in the base class. If the base class shall also be able to create elements, you may need some kind of factory method. Because you don't want the base kind of elements in the vector.