How to create a QMap of objects?
-
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 -
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)
-
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.
-
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();
}
@ -
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;
@ -
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!!!
-
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!!!
-
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.