Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to create a QMap of objects?

How to create a QMap of objects?

Scheduled Pinned Locked Moved General and Desktop
17 Posts 5 Posters 17.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    shorawitz
    wrote on last edited by
    #1

    How can I achieve having a QMap of objects something like below and then be able to access them and pass them to other objects? I keep running into issues due to "const" values.

    @
    QMap<QString,MyClass> myObjs;
    quint objTotal = 8;

    for (int i=0; i < objTotal; i++) {
    MyClass mc("paramA" + QString::number(i),"paramB" + QString::number(i),10);
    myObjs.insert("paramA" + QString::number(i),mc);
    }

    qDebug() << myObjs.value("paramA1").showData();
    @

    myclass.cpp
    @
    MyClass::MyClass(const QString &param1, const QString &param2, quint8 &DEBUG) {
    this->param1 = param1;
    this->param2 = param2;
    this->DEBUG = DEBUG;
    }

    void MyClass::showData() {
    qDebug() << param1 << param2 << DEBUG;
    }
    @

    1 Reply Last reply
    0
    • Q Offline
      Q Offline
      quendimax
      wrote on last edited by
      #2

      The value method return "const data type":http://doc.qt.nokia.com/4.7-snapshot/qmap.html#value:
      @const T value ( const Key & key ) const@
      Use
      @myObjs["paramA1"]@
      and read the "docs":http://doc.qt.nokia.com/4.7-snapshot/qmap.html

      And righter to make thе showData method constant.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        shorawitz
        wrote on last edited by
        #3

        Sorry, I typed the last line of the main block wrong. The "qDebug() << " shouldn't have made it in. But regardless, the code still doesn't compile with the changes Maksim suggested.

        I have read the docs, but I can't find anything there regarding errors that show up and don't show the line of user code that matches the error. Instead, QT Creator is giving me a more general error from the qmap header file:

        Updated main block:
        @
        QMap<QString,MyClass> myObjs;
        quint objTotal = 8;

        for (int i=0; i < objTotal; i++) {
        MyClass mc("paramA" + QString::number(i),"paramB" + QString::number(i),10);
        myObjs["paramA" + QString::number(i)] = mc;
        }

        qDebug() << myObjs["paramA1"].showData();
        @

        @
        no matching function for call to MyClass::MyClass() qmap.h 531
        candidates are: MyClass(const QString&, const QString&, quint8&)
        MyClass::MyClass(const MyClass&)
        @

        Now I understand what the "no matching function for call..." is trying to tell me. It just doesn't make sense why I'm getting that message. With the info I have, I'm no closer to understanding how to make a MAP of objects work.

        1 Reply Last reply
        0
        • BilbonSacquetB Offline
          BilbonSacquetB Offline
          BilbonSacquet
          wrote on last edited by
          #4

          This line is really suspect:
          qDebug() << myObjs["paramA1"].showData();

          Same for:
          qDebug() << myObjs.value("paramA1").showData();

          In both call you use a function returning 'void' (i.e. showData()). And the second problem with value() it returns a const instance which means that you should declare: void MyClass::showData() const;

          1 Reply Last reply
          0
          • S Offline
            S Offline
            shorawitz
            wrote on last edited by
            #5

            I forgot to take it out again. Bad me! I hand typed it in to the post. It's not in my working code.

            [quote author="BilbonSacquet" date="1321389819"]This line is really suspect:
            qDebug() << myObjs["paramA1"].showData();

            Same for:
            qDebug() << myObjs.value("paramA1").showData();

            In both call you use a function returning 'void' (i.e. showData()). And the second problem with value() it returns a const instance which means that you should declare: void MyClass::showData() const;[/quote]

            1 Reply Last reply
            0
            • S Offline
              S Offline
              shorawitz
              wrote on last edited by
              #6

              Ok. It has something to do with assigning the parameters in the Constructor of MyClass. If I create a separate function to assign the private variables, I can get it to work.

              My worry has been that I didn't want to have an instance of MyClass accessed without the default parameters set. That would predicate the need to have the "assignment" function run as soon as possible.

              1 Reply Last reply
              0
              • BilbonSacquetB Offline
                BilbonSacquetB Offline
                BilbonSacquet
                wrote on last edited by
                #7

                Go to the last word of my post, add simply a 'const' at the end of your 'showData()' function! :)
                @void showData() const {}@
                Or if you want to do a sin, use const_cast<>() ... :P

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  goetz
                  wrote on last edited by
                  #8

                  The Qt container classes work on assignable types.

                  bq. From the "Qt Container classes docs":http://developer.qt.nokia.com/doc/qt-4.7/containers.html [emphasis by me]
                  The values stored in the various containers can be of any assignable data type. To qualify, a type must provide a default constructor, a copy constructor, and an assignment operator. This covers most data types you are likely to want to store in a container, including basic types such as and , pointer types, and Qt data types such as QString, QDate, and QTime, but it doesn't cover QObject or any QObject subclass (QWidget, QDialog, QTimer, etc.). If you attempt to instantiate a QList<QWidget>, the compiler will complain that QWidget's copy constructor and assignment operators are disabled. If you want to store these kinds of objects in a container, store them as pointers, for example as QList<QWidget *>.

                  So in your case, you must provide:

                  • the default constructor MyClass(), or add default values to your parametrized constructor
                  • a copy constructor MyClass(const MyClass &other)
                  • an assignment operator MyClass &operator=(const MyClass &other)

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    shorawitz
                    wrote on last edited by
                    #9

                    Ah! There's the answer I was looking for and couldn't find on my own! Thank you Volker!!!

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      goetz
                      wrote on last edited by
                      #10

                      Another solution would be to use pointers, instead of values. This way you would not need the additional constructors and assignment ops.

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        shorawitz
                        wrote on last edited by
                        #11

                        I thought I tried to use a pointer, but I got a different error. I'll try it because of a new wrinkle.

                        On that note, is it true that because I'm NOT using a pointer for "myObjs" I lose all the values when the program goes out of scope of the "assignment" function? I'm noticing that the structure of the class values are there, but the data assigned in the "for" loop in "MyClass" is empty.

                        1 Reply Last reply
                        0
                        • K Offline
                          K Offline
                          Kxyu
                          wrote on last edited by
                          #12

                          Yes, it's true. If you want to use objects outside of the scope, you should create them with new

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            shorawitz
                            wrote on last edited by
                            #13

                            Ok. Here's where I hit the snag now. It all compiles fine, then I get a Segmentation fault. I just can't see the reason.

                            ObjsClass header file:
                            @
                            public:
                            ObjsClass();
                            void showData(QString&);

                            private:
                            QMap<QString,MyClass> *myObjs;

                            @

                            ObjsClass cpp file:
                            @
                            #include "objsclass.h"

                            ObjsClass::ObjsClass()
                            {
                            QMap<QString,MyClass> localObjs;

                            for (int i = 0; i < 8; i++) {
                                MyClass mc;
                                mc.assignVals("paramA" + QString::number(i),"paramB" + QString::number(i),10);
                                localObjs["paramA" + QString::number(i)] = mc;
                            }
                            
                            myObjs = &localObjs;
                            

                            }

                            void ObjsClass::showData(QString &index) {
                            (*myObjs)[index].showData();
                            }
                            @

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              goetz
                              wrote on last edited by
                              #14

                              It's not clear what goes out of scope in your program.

                              The myObjs object is alive as long as your instance of the ObjsClass class is alive. If you use a pointer for the map, you must create it with new:

                              @
                              myObjs = new QMap<QString, MyClass>;
                              @

                              You're doing it wrong™ in your constructor:
                              You create a local object localObjs on the stack in line 5. Then, in line 13, you assign the address of this local object to the myObjs pointer. But as soon as the constructor is done (line 14), the local localObjs object is destroyed. myObjs is still pointing to that no more valid object, hence the crash in the showData method.

                              You most probably don't need the map as a pointer.

                              What I meant, is, store MyClass pointers instead of MyClass objects inside the Map:

                              @
                              QMap<QString, MyClass *> myObjs;
                              @

                              http://www.catb.org/~esr/faqs/smart-questions.html

                              1 Reply Last reply
                              0
                              • S Offline
                                S Offline
                                shorawitz
                                wrote on last edited by
                                #15

                                Ah, yes! I can see it now. I've started down that path while waiting for a reply. Still hitting some seg faults, but I think I'm closer now to understanding this.

                                At this point, I'm not even sure I'm doing the whole concept correctly. I basically need to have access to the values stored in the myObjs container class in various functions in the ObjsClass. They don't really have to be in a class (but I think I might need that to have them created in the heap in order to have access to the values.) I'll meddle some more to see if I can make heads/tails of all this.

                                Java (and I'm not an expert there either) was little more forgiving, so I'm getting up to speed, just slowly.

                                Thank you all for the help!!!

                                1 Reply Last reply
                                0
                                • S Offline
                                  S Offline
                                  shorawitz
                                  wrote on last edited by
                                  #16

                                  Ok. Now a call to ObjsClass::showData(&index) will trigger "MyClass" to show the parameters.

                                  Maybe this thread can help someone else. Here's what the code looks like that does what I want.

                                  header file didn't change.

                                  objclass.cpp:
                                  @

                                  #include "objsclass.h"

                                  ObjsClass::ObjsClass()
                                  {
                                  myObjs = new QMap<QString,MyClass*>;

                                  for (int i = 0; i < 8; i++) {
                                      MyClass *mc = new MyClass();
                                      mc->assignVals("paramA" + QString::number(i),"paramB" + QString::number(i),i);
                                      //myObjs["paramA" + QString::number(i)] = mc;
                                      myObjs->insert("paramA" + QString::number(i),mc);
                                  }
                                  

                                  }

                                  void ObjsClass::showData(QString &index) {
                                  qDebug() << "looking for:" << index;
                                  myObjs->value(index)->showData();
                                  }

                                  @

                                  Thanks again for all of the help!!!

                                  1 Reply Last reply
                                  0
                                  • G Offline
                                    G Offline
                                    goetz
                                    wrote on last edited by
                                    #17

                                    Having it in a class as a container is a good idea. I do that in my project too. If you put them into a container as values (i.e. not as pointers), just make sure to have the implemented the assignment operators etc. It's not much work.

                                    Have a look at the following topcis of the "C++ FAQs":http://www.parashift.com/c++-faq-lite/

                                    • "Constructors":http://www.parashift.com/c++-faq-lite/ctors.html
                                    • "Assignment operators":http://www.parashift.com/c++-faq-lite/assignment-operators.html

                                    And read on that FAQs in general - it's a pretty good source of valuable information!

                                    PS:
                                    If your ObjsClass object is long living (which I assume), it is ok to have the myObjs as a regular member, not as a pointer.

                                    http://www.catb.org/~esr/faqs/smart-questions.html

                                    1 Reply Last reply
                                    0

                                    • Login

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • Users
                                    • Groups
                                    • Search
                                    • Get Qt Extensions
                                    • Unsolved