Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 the void 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 empty get_name() == "" to add my new item at the first empty slot you know.
    I know that the method I've written above with the m_object_i is incorrect but I'm wandering if there's something similar in C++ or Qt ?



  • Use the container classes such as QVector or QList for the purpose
    QVector< QObject * > m_vecObjects;



  • Use the container classes such as QVector or QList for the purpose
    QVector< QObject * > m_vecObjects;


  • Moderators

    @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



  • @nagesh

    Thanks for your advice, but it seems I've made something wrong because I get segmentation fault :/
    Now my class Bag only contains a QVector 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 class Player contains a pointer of the bag that I get with bag() 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.


  • Lifetime Qt Champion

    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 a QString).
    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 :
    The Bag class contains a QVector 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 :)


Log in to reply