While loop with similar variables
-
Hello,
I have a question that can seem stupid but I was using a method in web development to test many variables with similar name and I'm thinking if it's possible in C++ or maybe with Qt ?
For example :
I have a class Bag like this :class Bag { public: Bag(); Bag(Bag const& copy); Bag& operator=(Bag const& copy); ~Bag(); Object* get_object(int nb) const; int get_nb_object() const; void add_object(Object const& object); void set_object(int nb, Object const& object); private: Object *m_object_1; Object *m_object_2; Object *m_object_3; Object *m_object_4; Object *m_object_5; Object *m_object_6; Object *m_object_7; Object *m_object_8; Object *m_object_9; Object *m_object_10; };
As you can see, this bag containes 10 objects that only have
QString m_name
for the moment.
I'm thinking of how to do thevoid add_object(Object const& object);
function like this :void Bag::add_object(Object const& object) { int i = 1; while (m_object_i->get_name() != "") { i++; } delete m_object_i; m_object_i = object; }
So I want to test m_object_1 then m_object_2 then m_object_3...
To find the first that have an emptyget_name() == ""
to add my new item at the first empty slot you know.
I know that the method I've written above with them_object_i
is incorrect but I'm wandering if there's something similar in C++ or Qt ? -
@Tequiloutre
No,
as a compiled language, variable names in c++ mean (in the end) nothing!You may get away with something like this in JS or Python or something similar.
However in Qt, QObject based classes have the "object name" property that you can search the object tree for.
It is slow and I wouldn't recommend it.Do as @nagesh said, use a Vector, List or Array to store the object pointers
-
Thanks for your advice, but it seems I've made something wrong because I get segmentation fault :/
Now my classBag
only contains aQVector
declared like this in my bag.h :QVector< Object* > m_objects;
So if I understand good, this vector contains pointers of objects ?
So I tried to add some objects and get their name after that :
(For this example, the classPlayer
contains a pointer of thebag
that I get withbag()
function)Player *player_1 = new Player("Tequiloutre"); Object *object_1 = new Object("Orange"); Object *object_2 = new Object("Pamplemousse"); player_1->bag()->add_object(object_1); player_1->bag()->add_object(object_2);
The function
add_object
:void Bag::add_object(Object* object) { m_objects.append(object); }
All of this seems to work, I can see in the debugger that I get everything from player_1, even the two objects in my bag vector :
this @0x555555896070 Player m_bag @0x5555558c7e10 Bag m_objects <2 éléments> QVector<Object*> [0] @0x555555884790 Object m_name "Pamplemousse" QString [1] @0x55555579abb0 Object m_name "PS5" QString m_name "Tequiloutre" QString
But when I try to get the name of an object like this :
player_1->bag()->get_object(1)->get_name();
get_object()
on bag.cpp :Object* Bag::get_object(int nb) const { return m_objects.value(nb); }
get_name()
on object.cpp :QString Object::get_name() const { return m_name; }
I get a segmentation fault.
-
Hi,
You should start your application with the debugger. You'll see exactly where it crashes.
-
@Tequiloutre said in While loop with similar varaibles:
Object* Bag::get_object(int nb) const
You need to check whether the index "nb" is valid one or not.
For the value API if out bound index is passed it will return default-constructed value.use vector call "at" for accessing the element.
nb must be a valid index position in the vector (i.e., 0 <= nb< size())
-
@Tequiloutre said in While loop with similar varaibles:
Object* Bag::get_object(int nb) const
{
return m_objects.value(nb);
}Does your
Object
class have a default-contructor? (Not the one where you have to pass aQString
).
Even if you have one, but it doesn't initialize all members properly, you will get your segfault when trying to access them.-
If the index i is out of bounds, the function returns a default-constructed value. If you are certain that i is within bounds, you can use at() instead, which is slightly faster.
As @nagesh said, check if the index is within your container's bounds before returning anything. Then you also can use
m_objects.at(i)
, which is faster than.value(i)
(https://doc.qt.io/qt-5/qvector.html#value
and
https://doc.qt.io/qt-5/containers.html#default-constructed-value)EDIT:
@Tequiloutre said in While loop with similar varaibles:
delete m_object_i;
Any chance that you delete some pointers again, before the access happens? Like in your previous post? ;-)
-
-
Thank you all for your advices, I understand know how it works, here's what I've done :
TheBag
class contains aQVector
declared like this :QVector< Object* > m_objects;
I now manage and access the object on the
Bag
with those functions :void Bag::add_object(Object* object) { m_objects.append(object); } Object* Bag::get_object(int nb) const { return m_objects.at(nb - 1); } int Bag::get_size() const { return m_objects.length(); }
The segmentation fault I had was because I forgot to change the function to get all objects of the bag (I was going out of bounds)
So now to show all the objects of the bag I just have to do this :for (int i = 1; i < player_1->bag()->get_size() + 1; i++) { qDebug() << player_1->bag()->get_object(i)->get_name()); }
Thank you all again for your advices, this forum is awesome :D
-
@Tequiloutre said in While loop with similar varaibles:
for (int i = 1; i < player_1->bag()->get_size() + 1; i++) {
qDebug() << player_1->bag()->get_object(i)->get_name());Normally you would keep it at 0 and count from there to
size
. Get used to it :) It makes reading code and working with indices in C/C++ and other languages a lot easier, since it's usually like this.
So the first element is always at index 0 and index 1 is the second... and so on..return m_objects.at(nb - 1);
Unlike the line above, it also doesn't cause confusion, because you don't have to add/substract numbers here and there to make it work :)