QHash insert() ?

Du bist neu in der Welt von C++? Dann schau hier herein!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

RHBaum hat geschrieben:Besser: Smartpointer in c++ nutzen !
Noch besser: Referenzen (hast du ja schon geschrieben). Noch noch besser (wenn wie hier ID, Context, etc. im struct geführt werden, und deshalb eine Identifizierung nicht über eine Speicheradresse stattfindet): Values!
Letzteres aber nur dann, wenn du einem Objekt mehrfach einen Wert zuweisen willst (das geht so mit Referenzen nicht).
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Ok, habs nun mit Pointer und Referenz.

Jedoch will meine Roh-Methode nicht so:

Code: Alles auswählen

void DataController::addNew(q_int32 tID, QString tName, q_int32 tCat, q_int32 tCon)
{
	DataItem tDataItem (tDI, tName, tCat, tCon);
	this->dynamicData.insert(tID, tDataItem);
}
Am anfang habe ich zu Testzwecken beim initzialisieren des QHash mittels:

Code: Alles auswählen

//in ThisClass
DataController *pDataController;

void ThisClass::initQHash()
{
	pDataController = new DataController;
	pDataController->addNew(2511, tr("Heim"), 2121, 1272923);
	pDataController->addNew(2512, tr("Work"), 282, 1272963);
}
nur mist drin. WIe im Bild oben: Fehler CXX0030 usw.

Zur Info: Zeiger auf Datacontroller, dieser DataController hat wie gesagt eine QHash

Code: Alles auswählen

		QHash<q_int32, DataItem> dynamicData;
Ich sage danke für alle Hinweise.

Mfg Huck
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

huckleberry hat geschrieben:Ok, habs nun mit Pointer und Referenz.
Warum Beides?
Jedoch will meine Roh-Methode nicht so:

Code: Alles auswählen

void DataController::addNew(q_int32 tID, QString tName, q_int32 tCat, q_int32 tCon)
{
	DataItem tDataItem (>>>>>> tDI <<<<<<<, tName, tCat, tCon); Buchstabendreher?
	this->dynamicData.insert(tID, tDataItem);
}
Am anfang habe ich zu Testzwecken beim initzialisieren des QHash mittels:

Code: Alles auswählen

//in ThisClass
DataController *pDataController;

void ThisClass::initQHash()
{
	pDataController = new DataController;
	pDataController->addNew(2511, tr("Heim"), 2121, 1272923);
	pDataController->addNew(2512, tr("Work"), 282, 1272963);
}
Hör mal bitte auf, immer alles in Zeigern speichern zu wollen! pDataController ist eine Eigenschaft der ThisClass-Instanzen. Sie wird (wie ich das sehe) von ThisClass kontrolliert, sprich instanziiert, gekapselt und (hoffentlich auch) zerstört. Deshalb: Leg es auf den Stack! Nur weil das Zeiger-Gebastel Freakig ausschaut, ist es nicht besser. Zeiger dereferenziern kostet Zeit, vor allem die Instanziierung ist enorm teuer (dynamische Speicherallokation), und wird nicht wett gemacht durch die Speicherersparnis, wenn das Objekt nicht benötigt wird.
WIe im Bild oben: Fehler CXX0030 usw.
Ich hab den Thread mal nach nem Bild oder CXX0030 abgesucht - fehlanzeige.
Kannst du bitte statt der Fehlercodes die Meldungen posten? und die auch nicht als Screenshot deiner IDE, sondern als Text aus der IDE exportieren, und hier als Code posten?


Grüße
Franz
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Hallo franzf,

also der Grund, warum ich zur Zeit soviel mit Zeigern und Referenzen usw. herummache, ist schlicht der, dass ich noch sehr unsicher bin (wie ihr bestimmt gemerkt habt); so wollte ich das mir verinnerlichen.

Zum Bild: http://www.qtforum.de/forum/files/forum_120.jpg hier ein paar Postings vorher.
Fehlermeldung :"CXX0030: Error: Expression cannot be evaluated"

Eine Fehlermeldung gibt es konkret im Debug-Fenster keine. Wie gesagt, wenn ich mit der Maus im Code auf den Zeiger gehe..
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Mir wurde jetzt gerade echt schlecht beim Anschauen des Screenshots :D
Kriegst du von deinem Debugger denn keinen ordentlichen CallStack? In dem Screenshot gibts keine Infos zu den Typen oder Methoden, nur die Variablennamen und irgend welche Adressen...

Google nach deiner Meldung gibt ein paar Ergebnisse, vielleicht bringen die dich weiter.

Ansonsten: Wir brauchen kompilierbaren Code! Ohne kann man nur raten. Ich bin mir aber ziemlich sicher, dass du irgendwo mit deinen Zeigern murkst :D
Sollte dein Programm zu groß sein, extrahiere die problematischen Klassen, und baue einen minimalen Test für diese Klassen, der natürlich kompilieren sollte, sonst hilfts nix ;)
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Anbei die auf das wesentliche vereinfachten Quellcodes. Meine Vermutung:
Das myQHash ist im dem Header deklariert, sollte aber irgendwo im Source auch definiert sein?

Code: Alles auswählen

private: 
      QHash<q_int32, DataItem> myQHash; 

DataItem.cpp

Code: Alles auswählen

#include "DataItem.h"

DataItem::DataItem()
{
	this->dataID = 0;
	this->dataCon = 0;
	this->dataCat = 0;
	this->dataName = "defName";
}

DataItem::DataItem(q_int32 tId, QString tName, q_int32 tCat, q_int32 tCon)
{
	this->dataID = tId;
	this->dataCon = tCon;
	this->dataCat = tCat;
	this->dataName = tName;
}

q_int32	DataItem::getID() const { return this->dataID; }

QString	DataItem::getName() const { return this->dataName; }

q_int32	DataItem::getCat() const { return this->dataCat; }

q_int32	DataItem::getCon() const { return this->dataCon; }

DataItem::~DataItem(void) {}
DataItem.h

Code: Alles auswählen

#pragma once
#include <QString>

class Item
{
public:
	Item();
	Item(q_int32 tId, QString tName, q_int32 tCat, q_int32 tCon);
	~Item(void);

	q_int32	getID() const;
	QString		getName() const;
	q_int32	getCat() const;
	q_int32	getCon() const;
	
private:
	q_int32	ID;
	QString		Name;
	q_int32	Cat;
	q_int32	Con;
};
DataController.cpp

Code: Alles auswählen

#include <QHash>
#include "DataController.h"

DataController::DataController(void)
{
    // muss hier nicht sowas wie QHash<q_int32, DataItem> myQHash = new QHash(); ????
}

void DataController::addNew(DataItem& tPI) { this->myQHash.insert(tPI.getID(), tPI); }

void DataController::addNew(const DataItem * const tPI) { this->myQHash.insert(tPI->getID(), *tPI); }

void DataController::addNew(q_int32 tID, QString tName, q_int32 tCat, q_int32 tCon)
{
	DataItem tPI (tID, tName, tCat, tCon);
    this->myQHash.insert(tID, tPI);
}

DataController::~DataController(void) {}
DataController.h

Code: Alles auswählen

#pragma once

#include <QtGui>
#include <QString>
#include <QHash>
#include "DataItem.h"

class DataController
{
public:
	DataController(void);
	~DataController(void);
	void addNew(DataItem& tPI);
	void addNew(const DataItem * const tPI);
	void addNew(q_int32, QString, q_int32, q_int32);

private:
		QHash<q_int32, DataItem> myQHash;
};
MyDockWidget.cpp

Code: Alles auswählen

#include "MyDockWidget.h"
#include <QtGui>

MyDockWidget::MyDockWidget( QWidget *a_parent )
{
	this->myDataController = new DataController();
	myDataController.addNew(2511, tr("Heim"), 20481, 1272923, 6230100, 0);
	myDataController.addNew(2512, tr("Work"), 20482, 1272963, 6230160, 0);
	// Breakpoint here
}
MyDockWidget.h

Code: Alles auswählen

#ifndef MY_DOCK_WIDGET_H
#define My_DOCK_WIDGET_H

class MyDockWidget
{
    Q_OBJECT

    public:
        /// @brief constructor
        MyDockWidget( QWidget *parent);
		DataController myDataController;
};
#endif // MY_DOCK_WIDGET_H
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Habs nun mit dem Debugger analysiert:

Code: Alles auswählen

void DataController::addNew(q_int32 tID, QString tName, q_int32 tCat, q_int32 tCon) 
{ 
   DataItem tPI (tID, tName, tCat, tCon); 
    this->myQHash.insert(tID, tPI); 
}
In der Zeile mit DataItem tPI(tID, tName, tCat, tCon); ist alles noch korrekt. In tPI sind die richtigen Werte drin, etc.: (tID=2511, tName=tr("Heim"), tCat= 20481, tCon=1272923).
Das Problem entsteht anscheinend beim "inserten". Danach steht murks in myQHash: statt
2511,"Heim", 20481, 1272923 steht da
1, BadPtr, 262148, 17 ?!?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Sry, aber das ist doch ein Witz? Hier ist NICHTS kompilierbar!
- Keine main
- Warum MyDockWidget?
- MyDockWidget hat ein Q_OBJECT, aber erbt von nichts
- include-guards fehlen (#pragma once geht mit GCC nicht!)
- q_int32 gibts nicht (heißt qint32)

Bis hierher hab ich noch brav alles selber geändert.

- Klassendefinition von "DataItem" fehlt - die heißt bei dir schlicht "Item", wird aber überall mit "DataItem" verwendet.

Hier steig ich aus...
Wenn du WIRKLICH willst, dass wir dir helfen, separier die Klassen in ein eigenes Projekt, so dass dieses auch wirklich kompiliert.
Starte dein Programm und schau, dass es auch wirklich den Fehler gibt, den du bekommst, denn ein Programm, das fehlerfrei läuft, kann man schwer debuggen.
Und jetzt bereinigst du dein Projekt von allen Objectfiles, Libraries, Binaries, ... und packst dann NUR DIE SOURCEFILES in ein .zip.
Das entpackt sich schnell, das mühsame Kopieren und selber abspeichern entfällt.
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Tut mir leid für die Umstände, die ich bereitet habe. Ich habe eben alles manuell geändert; in der Hoffnung, dass es sich so compilieren lässt.

In den Sourcecodes waren jede Menge Sachen, die mit meinem Problem absolut nichts zu tun haben; deswegen habe ich alles GUI-Zeug etc. ausgenommen.
Weiterhin gehören die Codes dem Hersteller, wo grad alle irgendwie im Urlaub o.ä. sind. Deswegen kann ich da keine Quellcodes herausgeben und bitte dafür um Verständnis.

Ich habe mein Problem vorhin eingrenzen können. Mein Spezialobjekt DataItem tPI wird von QHash::insert() nicht korrekt "insertet".
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Hier habe ich nun das kleine Projekt als VS Projekt erstellen können.

Es ist ausfühbar und kann den initialen QHash-Fehler reproduzieren.
Dateianhänge
deldel3.zip
(2.96 KiB) 284-mal heruntergeladen
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Beitrag von brax »

Ich kann kein Problem entdecken... Meines Erachtens macht das Programm alles wie gewünscht.

Da ich im VS die Qt Integration nicht installiert habe (die zwingt leider manchmal den Debugger in die Knie und zeigt eh oft nicht die richtigen Inhalte von Listen, Maps etc. an) habe ich DataController testweise noch um eine getItem Methode erweitert:

Code: Alles auswählen

DataItem* DataController::getItem(qint32 key) {
	if (myQHash.contains(key)) return myQHash[key];
	return NULL;
}
Die main sieht dann bei mir so aus:

Code: Alles auswählen

    DataController myDataController;
    myDataController.addNew(2511, "Heim", 20481, 1272923);
    myDataController.addNew(2512, "Work", 20482, 1272963);
    DataItem* pI1 = myDataController.getItem(2511);
    DataItem* pI2 = myDataController.getItem(2512);
und pI1 und pI2 sehen völlig korrekt aus.

Btw. das VS Projekt war nicht wirklich das, was franzf sich vorgestellt hat glaube ich. Er sprach vom GCC. Daher wäre eine .pro Datei deutlich angenehmer gewesen (dann hätten es übrigens auch VS Benutzer leichter, weil sie die Include-Verzeichnisse und Linker-Einstellungen nicht anpassen müssten). Das Austauschen von #pragma once mit echten Includeguards, so wie von franzf gefordert wäre auch nicht so große Arbeit gewesen. Nur für die Zukunft.... wenn Du Hilfe willst, solltest Du es den Helfenden möglichst leicht machen.
huckleberry
Beiträge: 115
Registriert: 2. Oktober 2010 17:07

Beitrag von huckleberry »

Wegen dem unverschämten Code von mir, bitte ich alle nochmal um entschuldigung. Das war gestern auf die schnelle; hatte nicht daran gedacht, dass man noch soviel korrigieren muss.
brax hat geschrieben:Da ich im VS die Qt Integration nicht installiert habe (die zwingt leider manchmal den Debugger in die Knie und zeigt eh oft nicht die richtigen Inhalte von Listen, Maps etc. an) habe ich DataController testweise noch um eine getItem Methode erweitert.
Tatsächlich, das wars! pI1 und pI2 werden nun auch bei mir korrekt angezeigt.
Also wenn das Qt-addon für VS dann alles richtig anzeigen kann, werde ich es dann installieren.

THX und MfG Huck
Antworten