C++, Objects on vector - c++

I wanna store objects on vectors. But I do not know why it does not work.
‪#‎include‬ <iostream>
#include <vector>
using namespace std;
I have a Persona class in the Persona.h file. And it only has two method:
The default constructor and a method called mensaje(), both are public and it does not have any private member.
#include "Persona.h"
int main()
{
vector<Persona> personas;
Persona persona1;
Persona persona2;
personas.push_back(persona1);
personas.push_back(persona2);
vector<Persona>::const_iterator p;
for(p = personas.begin(); p <= personas.end(); p++) {
Here is where I get the error message
p.mensaje();
}
}
I think problem is the way that I am trying to call 'p'.
Is right that I try to use const_iterator instead of any other type?

p is iterator not object itself, you need to dereference it:
(*p).mensaje();
OR
p->mensaje();
And
update:
for(p = personas.begin(); p <= personas.end(); p++) {
to:
for(p = personas.begin(); p != personas.end(); p++) {
^^^^^^

You are trying to call a non-const method on a const object (the object referenced by a const iterator). Since the mensaje() method does not modify the object, it should be declared const, like so:
void Persona::mensaje() const;
After you make this change, you should be able to call the method on the const object (reference) returned from the const iterator.
(...in addition to the other syntax errors mentioned in other answers.)

Related

Access to STL lists of pointers to objects

I wonder how to get access to element of list that contains pointers to objects. I want to achieve that without dereferencing. Propably it will be much easier if i just show what i want. So I have list:
list<ObjectClass*> nameOfObject;
and I have method:
bool collision(list<ObjectClass*>::iterator&);
And inside definition of that method I have:
{
if((*nameOfObject)->getSprite()) return true;
else return false;
}
What i want is to getSprite without needing to dereference nameOfObject inside method, so something like that:
{
if((nameOfObject)->getSprite()) return true;
else return false;
}
Everything that i tried is not working. I thought that it would be easy but i really don;t get it. Any ideas? I will add that list has to contain pointer to the objects, because of polimorphysm.
list<ObjectClass*>::iterator&
It's unclear why iterator is passed by reference.
*nameOfObject
This is ill-formed because std::list doesn't have indirection operator. I suspect that you may have shadowed that variable, and forgotten to include the shadowing variable in the example.
What i want is to getSprite without needing to dereference nameOfObject inside method,
Then you need to have an instance of a class with getSprite member function in the class rather than a pointer/iterator to such. If you do have a pointer/iterator, then there is no way to access the pointed object through the pointer without indirection.
so something like that:
(nameOfObject)->getSprite()
That does dereference nameOfObject. -> is the indirecting member access operator. It is also ill-formed with a list.
Any ideas?
Avoid wanting impossible things ¯\_(ツ)_/¯
You usually don't pass single iterator around.
If you want single object, pass single object (whether by reference or pointer)
I write an example code, hope it helps.
fIter is probably what most close to what you currently have
f is demonstrate you can iterate collection without directly use iterator
//
// https://stackoverflow.com/q/63156916/5980430
//
#include <list>
#include <iostream>
class ObjectClass{
public:
int spriteID;
int getSprite(){return spriteID;}
};
//your *collision* function
void collision(ObjectClass& obj){
std::cout << obj.getSprite() << '\n';
}
void f(std::list<ObjectClass>& objs){
for (auto& obj : objs){
collision(obj);
}
}
//even with iterator, you dereference it before pass in other functions
void fIter(std::list<ObjectClass>& objs){
for (auto it = objs.begin(); it != objs.end(); ++it){
collision(*it);
}
}
int main(){
std::list<ObjectClass> objects;
objects.push_back({1});
objects.push_back({2});
objects.push_back({3});
f(objects);
fIter(objects);
}
https://wandbox.org/permlink/SgI5ibjaIXd644DH

Modifying elements in a STL List - C++

I am attempting to construct a binary search tree using a generalized list in C++.
class Element
{
private:
list<Element*> _children;
char* _name;
// and other data members/methods...
}
As you can see, I have a class "Element" and it has a list "_children" of Element pointers.
I am trying to access these children so that I may add children to them and so forth...
However, I cannot modify these values with my current method of using a "const_iterator" and my reason for doing that is that the "begin()" method of _children returns a const_iterator.
Someone help? Thank you :)
UPDATE: Thank you all so much... It turns out, I mistakenly had a method return a const reference of the _children data member.
const list<Element*>& getChildren();// return [_children]
I just deleted const and it works perfect now. Thank you! :D
The begin function will return a const_iterator if the list is const. So for the _children list you should be able to just get the standard iterator to let you perform non-const operations on it:
list<Element*>::iterator it = _children.begin();
This however won't work if your passing off a const reference to the list and then trying to get the non-const iterator from that. Something like this would not be allowed:
void doSomething( const list<Element*>& l )
{
list<Element*>::iterator it = l.begin();
}
You would need to instead pass a non-const reference to the list.
The other case where this would be not allowed is in a const function, i.e.
void doSomething() const
{
list<Element*>::iterator it = _children.begin();
}
But would need to see more of your code to confirm if you're doing this or not.
If you want to use _children as an array, how about trying std::vector class instead of std::list?
Here's usage.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
for (int i = 0; i < list.capacity();++i){
std::cout << list[i] << std::endl;
}
return 0;
}

Pointer to Element in Vector

I am farily new to c++ and have already read some topics about storing pointers to objects or the objects themselves in a vector.
I decided to store the objects in the vector, because I do not push_back many objects at runtime, the vector is just created once and leaved like this.
My problem now is, that I have another object that gets a vector as argument and searches for a certain object in the passed vector. If it finds this object, it stores a pointer to it, if not, the variable is set to NULL.
Eventhough I do not push_back any items, the pointer seems to point to a wrong location in other functions.
The object that searches for the element in the vector has a public function in which the pointer should be returned. It would be very slow if I search for the object at every function call, so this should not be an option.
Are there other solutions or do I have to switch to a vector of pointers?
Some code snippets:
Constructor of the object that searches the vector:
MySearch::MySearch(QVector<Obj> objVector)
:objVector(objVector) {
found = NULL
foreach(Obj o, this->objVector) {
if(..found..) {
found = &o;
break;
}
}
}
Getter function:
Obj* MySearch::getObject() {
return found;
}
The problem is because the variable o is local and will be out of scope as soon as the loop ends. If you take the address of the vector element instead of the o, it will works.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class MySearch
{
public:
MySearch(const vector<string> &items)
: items_(items)
{
// Skipping validation
found_ = &(items_[5]);
}
string *getObject() {return found_;}
private:
vector<string> items_;
string *found_;
};
int main()
{
string str = "test#";
vector<string> aux;
for (int i = 0; i < 10; ++i)
aux.push_back(str + (char)('0' + i)); // test#0 ... test#9
MySearch ms(aux);
cout << *(ms.getObject()) << endl; // test#5
return 0;
}
foreach(Obj o, this->objVector) {
if(..found..) {
found = &o;
break;
}
} // life time of o ends here.
o resides on stack and it's life-time is limited to the loop only. Having reference to it and later returning causes undefined behavior.
If you were to use BOOST_FOREACH (from the boost C++ libraries), then you could use a non-const reference to the objects in the vector. Q_FOREACH does not support non-const references:
BOOST_FOREACH(Obj& o, this->objVector) {
if(..found..) {
found = &o;
break;
}
}
Alternatively use iterators and a for loop.

Problems when looping through a list of pointers - C++

I have a list of pointers to a base abstract class (Entity)
std::list<Entity*> m_entities;
I have created a typedef for iterating through this class
typedef std::list<Entity*>::const_iterator entityIter;
I then try and iterate through each pointer in the list
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
const Entity &e = *i; // ERROR
e.DoStuff();
}
I get the following error when attempting to reference each pointer
IntelliSense: no suitable constructor exists to convert from "Entity *const" to "Entity"
What have I done incorrectly?
EDIT:
I have tried to use std::shared_ptr
std::list<std::shared_ptr<Entity>> m_entities;
I can't add to the list this way though
Entity::Entity(Game *game)
: m_game(game)
{
m_game->g_idGenerator->generateNewID();
m_game->m_entities.push_back(this); // ERROR
}
Using the following
m_game->m_entities.push_back(std::shared_ptr<Entity>(this));
gives me this error
error C2664: 'void std::list<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from >'Entity' to 'std::tr1::shared_ptr<_Ty> &&'
EDIT 2:
Current code summary
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
// *i dereferences the iterator and returns an Entity*
// **i would additionally deference the pointer
// Adding 'const' infront of Entity means that I can't alter the Entity
Entity &e = **i;
e.draw(dt); // Causes access violation error with standard pointers
}
Have tried converting to std:shared_ptr to see if it would avoid the error triggered by the code above.
However, I am now having trouble adding the Entity to the list of std::shared_ptr
m_game->m_entities.push_back(std::shared_ptr<Entity>(this));
So in summary I have the access violation error with a standard pointer and I can't add to the list with a shared_ptr.
Populating the list is done via the constructor of the base Entity class
Entity::Entity(Game *game)
: m_game(game)
{
m_game->g_idGenerator->generateNewID();
// shared_ptr version
m_game->m_entities.push_back(std::shared_ptr<Entity>(this)); // ERROR C2664
// raw pointer version
//m_game->m_entities.push_back(this); // ACCESS VIOLATION ERROR when calling methods
}
const Entity &e = *i;
*i dereferences the iterator and returns an Entity*.
**i would additionally deference the pointer.
To avoid keeping the reference around, you can use (*i)->memberFunction(...);
Don't forget that if you allocated the Entity's with operator new that you also need to operator delete them.
Here is an example using std::shared_ptr since your code is looking to complex to discuss on a page.
I created a trivial Entity class and used it in std::shared_ptr. I put the same std::shared_ptr<Entity> multiple times purely for demonstration that std::shared_ptr manages this information including copying itself into the list.
#include <memory>
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Entity {
private:
string name;
public:
Entity(const std::string& n) :
name(n)
{ }
const string& getName() {
return name;
}
};
int main(int argc, char** argv) {
list<shared_ptr<Entity> > l;
shared_ptr<Entity> sp(new Entity("Repeated!"));
l.push_back(sp);
l.push_back(sp);
l.push_back(shared_ptr<Entity>(new Entity("Foo")));
l.push_back(sp);
l.push_back(shared_ptr<Entity>(new Entity("Bar")));
l.push_back(sp);
for(list<shared_ptr<Entity> >::const_iterator iter = l.begin();
iter != l.end(); ++iter)
{
cout << ">> " << (*iter)->getName() << endl;
}
};
Note: There is a difference between you putting the exact same raw pointer into multiple std::shared_ptr objects and copying a std::shared_ptr as push_back does. The latter case is fully managed by std::shared_ptr while the former case has each std::shared_ptr attempting to manage independently.
Option A) You wanted to access the elements and gurantee you do not change them:
typedef std::list<Entity*>::const_iterator entityIter;
std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
const Entity &e = **i; // ERROR
e.DoStuff();
}
Option B) You wanted to access the elements and change them:
typedef std::list<Entity*>::iterator entityIter; // no const_
std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
Entity &e = **i; // ERROR
e.DoStuff();
}

c++ iterator confusion

I have a vector<list<customClass> >
I have an iterator vector<list<customClass> >::const_iterator x
When I try to access an member of customClass like so:
x[0]->somefunc(), I get errors of a non-pointer type/not found.
Here's a complete working snippet. To answer your question, the line with the comment [1] shows how to dereference the const_iterator, while comment [2] shows how to dereference using the operator [].
#include <vector>
#include <list>
#include <iostream>
class Foo
{
public:
void hello() const
{
std::cout << "hello - type any key to continue\n";
getchar();
}
void func( std::vector<std::list<Foo> > const& vec )
{
std::vector<std::list<Foo> >::const_iterator qVec = vec.begin();
qVec->front().hello(); // [1] dereference const_iterator
}
};
int main(int argc, char* argv[])
{
std::list<Foo> list;
Foo foo;
list.push_front(foo);
std::vector<std::list<Foo> > vec;
vec.push_back(list);
foo.func( vec );
vec[0].front().hello(); // [2] dereference vector using []
}
The iterator dereferences to a list. If you want to access an object in that list, then you will have to use the list methods to do so. However, since stl lists don't overload the index operator, that won't be a valid option.
This will let you call somefunc on the first element in the list:
(*x).front().somefunc();
On the other hand, if you want an iterator for your list, you can do something like this:
list<customClass>::const_iterator listIterator = (*x).begin();
listIterator->somefunc();
iterator class does not provide operator[] hence you can not use it like that . You should use it as x->somefunc()
x is an iterator, which acts like a pointer - it points to a list. So you can only use functions which are members of std::list.
The const iterator will dereference to a list<customClass> object not a pointer to that list. You'd have to access the index in that list for the class...
Ignoring error checking:
(*x)[0].somefunc()
if you want direct access the list and vector class already implement the [] operator, so just access it directly: vectorObj[x].someFunc();
iterator are for going through the list (to iterate it like the name suggests), use it for that.