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

Appending to QList, QVector etc. not working.



  • Hi,

    it's probably a very basic newbie question, but I can't seem to figure out, what I'm doing wrong.
    What I want to achieve is very very simple. I just want to save some of my objects in a list. Coming from Java I just looked up what the best replacement for an ArrayList would be. So I tried the following:

    1. I gave my class a member:
    private:
        QVector<Ship *> placedShips;
    
    1. I added stuff to it:
    getPlacedShips().append(s);
    
    1. I tried to access it (just for testing):
    std::cout << getPlacedShips().first()->getName().toStdString() << std::endl;
    

    When it comes to accessing the vector the program crashes. So I thoght it could be that the vector isn't initialized. So I tried to do that by adding placedShips() to my initialization list. No success. Also placedShips(new QVector<Ship*>) didn't work out.
    The second attempt with the following error:

    "no matching constructor for initialization of 'QVector<Ship *> candidate constructor not viable: no known conversion from 'QVector<Ship *> *' to 'const QVector<Ship *>' for 1st argument; dereference the argument with *"

    So I tried to do what the error told my to try, without success.
    My next guess was trying like I'm used to: In the constructor body.

    placedShips = new QVector<Ship*>;
    

    It gave me:

    "no viable overloaded '=' candidate function not viable: no known conversion from 'QVector<Ship *> *' to 'const QVector<Ship *>' for 1st argument; dereference the argument with *"

    So. I'm quite confused. The vector object in't declared constant and yet it's saying so. Why is it so difficult to get a simple list working and what am I doing wrong?

    Thanks for your time :D



  • @m1212e said in Appending to QList, QVector etc. not working.:

    getPlacedShips().append(s);

    The above call is meaningless. Why are you appending to a function call, and not to the placedShips object that you created?

    the way you defined it, it is a container of pointers. Make sure you are only trying to insert pointers into it.

    And read and understand the documentation for the QVector to make sure you're doing valid operations on it.

    QVector<Ship*> ships;
    Ship* p{new Ship};
    ships.append(p);
    

    Keeping in mind that you are responsible for manually deleting the objects whos pointers are stored in the container, when you delete the container...which makes your container of pointers a less than desirable design pattern in the first place. You get into the classical design problem of who owns the object: the container or the var used to create it. There is no implicit reference counting garbage collection in the base Qt containers, like there would be in JAVA.



  • Well, it's my standart getter method. Its implementation goes as follows:

    QVector<Ship *> Board::getPlacedShips()
    {
        return placedShips;
    }
    

    and all it does is giving back the member object. It's done for information hiding purposes, I tought C++ had the same unwritten rules regarding object oriented programming?

    I made sure that I add the datatype the vector needs which, in this case, is a pointer to a ship object. All the memory should be cleaned automatically in this case via the parents of the objects.

    So your theory seems to be right, I can't use my getter function for appending to the list. When I do the call directly it works.
    But now I'm even more confused because a few lines below it works. It's two lines below and it works. So when I wan't to call the append function I can't use my getter method, but when I want to give out a test via cout I can. It just makes absolutely no sense to me...



  • @m1212e said in Appending to QList, QVector etc. not working.:

    QVector<Ship *> Board::getPlacedShips()
    {
    return placedShips;
    }

    So you want to return a "copy" of the private member container? More JAVAisms. LOL

    IIRC my JAVA, the code you wrote above would return a "handle" to the existing private object. In C++ it's gonna copy the object.



  • @Kent-Dorfman

    For what it's worth, in C++ I prefer to pass containers by reference as parameters to methods instead of playing with method return values and worrying about copy or reference issues.

    my methods usually look like

    int method(container& o, const int other_stuff=0);

    The return value is used as a status indicator and the container can be modified in the method. =0 means suppy a default value to other_stuff if I call the method with only the first parameter.


  • Lifetime Qt Champion

    Hi
    as @Kent-Dorfman says you are returning a copy of the placedShips, not the list itself

    QVector<Ship *> Board::getPlacedShips()
    {
    return placedShips;
    }

    should be

    QVector<Ship *> & Board::getPlacedShips()
    {
    return placedShips;
    }

    if you wish to change the list from outside.



  • @mrjj
    Thank you guys very much!