Probleme mit C++ Referenzen

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Probleme mit C++ Referenzen

Beitrag von Illuminatus »

Hi ich bin neu bei C++ und komme aus der Java Ecke.

Ich habe das Konzept mit den Referenzen nicht ganz verstanden (vor allem im Vergeil zu Pointern).

Kann mir wer sagen warum das hier nicht funktioniert:

Code: Alles auswählen

ParsingThread::ParsingThread(QObject *parent, QString paramFile, QString *array) :
    QObject(parent)
{
    fileName = new QString(paramFile); // invalid conversion from QString* to char
}
Laut Assistant müsste das doch der Copy Constructor sein???
QString::QString ( const QString & other )
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

So wie Du de Code gepostet hast kommt die Fehlermeldung garantiert nicht.
Und warum den QString mit new erzeugen anstatt einfach eine ganz normale member-Variable?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit C++ Referenzen

Beitrag von franzf »

Illuminatus hat geschrieben:Laut Assistant müsste das doch der Copy Constructor sein???
QString::QString ( const QString & other )
Nicht nur laut Assistant. So schaut der immer aus, egal für welche Klasse. Aber wo ist das Problem?
Dass du ihm ein "QString paramFile" übergibst und keinen "const QString& paramFile"? Das ist kein Problem, der Parameter im Copykonstruktor sagt "nimm das übergebene Objekt per Referenz". Da hat der Verwender keine Chance, etwas per Kopie zu übergeben :P
Außerdem solltest du dich von allen Javaismen freimachen. In Java wird (fast) alles per Referenz weitergegeben, in C++ per Kopie, wenn du nichts anderes angibst (hängt vom Zieltyp einer Zuweisung ab).
Auch (wie Christian schon moniert hat) ist in C++ die Erstellung mittels new nur in Begründeten Fällen nötig, in Java ist "new" das einzige Sprachmittel, um ein Objekt zu erstellen.
kater
Beiträge: 306
Registriert: 29. Dezember 2009 01:13
Wohnort: Darmstadt

Beitrag von kater »

Die Fehlermeldung hat nichts mit Pointer, nicht mit Referencen und auch nichts mit Konstruktoren zu tun.

Ich nehm stark an, der Typ von filename ist char, und nicht QString*. Zumindest geht das auch der Meldung herraus.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

Ah okay, in welchen Fällen benutzt man dann "new"?

Um Objekte auf dem Heap zu erzeugen? Also nur für Objekte die dynamisch sich während der Laufzeit oder ihrer Lebenszeit vergrößern/verkleinern?

Gibt es noch andere Einsatzarten für new?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Illuminatus hat geschrieben:Um Objekte auf dem Heap zu erzeugen? Also nur für Objekte die dynamisch sich während der Laufzeit oder ihrer Lebenszeit vergrößern/verkleinern?
Ersteres ja. Zweiteres nein. Du denkst da an Arrays. Ein Zeigertyp ist aber schon noch was anderes. Du brauchst ihn z.B., wenn ein Wert nur erzeugt werden soll, wenn es benötigt wird, bis dahin mit NULL initialisiert. Oder im Zusammenhang mit Polymorphie (Basisklassenzeiger).

Code: Alles auswählen

class Base {
};
class Derived : public Base {
};
class User {
Base* b; // Eine Referenz erlaubt kein neusetzen! Referenzen können nicht im Programmverlauf auf was neues zeigen, Zeiger schon
  public: setMember(Base* newB) {
    b = newB;
};
/// main
User u;
u.setMember(new Base);
u.setMember(new Derived);
// ACHTUNG!! obige zwei Zeilen erzeugen ein Memory Leak, das ist ein Nachteil von dynamischen Objekten.
// Man muss sich um die Zerstörung selber kümmern, C++ kennt keinen Garbage Collector!
Oder um sicher zu gehen, dass das Objekt den aktuellen Scope überlebt.

Code: Alles auswählen

int& getInt() {
    int ret = 10;
    return ret;
}
// gibt eine Referenz auf ein Objekt zurück, das bei Verlassen von getInt() wieder zerstört wird -> ungültige Referenz!
// mit Zeigern kein Problem:

int* getIntPtr() {
    int* ret = new int(10);
    return ret;
}
uswusf. Mit der Zeit kriegst du schon raus, wann du mit Values, wann mit Referenzen und wann mit Zeigern arbeiten musst.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

Okay und wie is das bei folgendem:

Code: Alles auswählen

// Conversion to QList item
            QList<QStandardItem *> itemsList;

            for(int i = 0; i< elements.size(); i++)
            {               
                QStandardItem *item = new QStandardItem(elements.at(i));
                itemsList<<item;
                // free pointer
                item = 0;
            }
            model->appendRow(itemsList);
(a) Ist es hier ein Problem, dass ich die itemsList auf dem Stack erstelle, da ich sie ja später meinem QStandardItemModel(model) übergebe?

(b)Im Galileo Buch:Qt4 Entwicklung mit C++ steht auf Seite 58, dass man jedes Qt Objekt mit Parent Zeiger auf dem Heap erstellen soll....

Kann mir wer erklärn warum???
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

a) nein, ist kein Problem, da sich das model keinen Zeiger/Referenz auf das temporäre Objekt speichert, sondern entweder die Items einzeln in eine eigene Struktur kopiert, oder gleich die ganze Liste (ich bin mit den Interna des QStandardItemModels nicht vertraut ;))

b) Das liegt an einer Spezialität von QObject. Ein QObject löscht im Destruktor alle children. Wenn ein child als automatisches Objekt (also nicht dynamisch) mit einem parent erzeugt wurde, bekommst du eine "double deletion": Das Objekt wird einmal vom parent (via QObject-Hierarchie) zerstört, zum zweiten wenn es seine Gültigkeit verliert. In jedem Fall stürzt das Programm ab.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

Und dieses double deletion kann ich dann folglich verhindern indem ich alle von Q_Object abgeleiteten Objekte mit new erzeug (also jedenfalls diejenigen die ein parent Object haben) ?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Illuminatus hat geschrieben:Und dieses double deletion kann ich dann folglich verhindern indem ich alle von Q_Object abgeleiteten Objekte mit new erzeug (also jedenfalls diejenigen die ein parent Object haben) ?
Genau, und am besten immer, denn reparenting findet öfter statt, als dir bewusst ist (ein QWidget in ein Layout packen, z.B.). Ein QObject als Member, der in so einer QObject-Hierarchie steckt, darf deshalb auch nicht selber im Destruktor gelöscht werden, sonst gibt es natürlich wieder das gleiche Problem ;)

Aber bitte jetzt nicht anfangen und kein QObject (und Derivate) mehr löschen. Du musst einfach aufpassen. Freie QObjects ohne parent kommen sehr wohl vor, diese müssen auch zerstört werden. Ob jetzt ein QObject einen parent hat oder nicht, erfährst du, wenn object->parent() NULL zurück liefert. Aber normalerweise weiß man, ob ein QObject einen parent hat oder nicht, deshalb jetzt nicht exzessiv nach parent() testen anfangen ;)
Antworten