[c++] struct als Referenz zurückgeben

WingMan81

Grünschnabel
Hallo,

ich versuche mich gerade an einem kleinen C++ Programm in Kombination mit Qt. Die Qt Anbindung ist auch gerade gar nicht das Problem, viel mehr funktioniert die Rückgabe einer Struktur als Referenz nicht.

Hier erst einmal der Quelltext:
mainwindowimpl.h
C++:
#ifndef MAINWINDOWIMPL_H
#define MAINWINDOWIMPL_H
//
#include <iostream>
#include <string>
#include <QMainWindow>
#include <QFileDialog>
#include <QFile>
#include <QDate>
#include "ui_mainwindow.h"

using namespace std;
//
class MainWindowImpl : public QMainWindow, public Ui::MainWindow
{
Q_OBJECT
public:
	MainWindowImpl( QWidget * parent = 0, Qt::WFlags f = 0 );
	
	
private:
	void setFileText();
	void setContentText();
	struct gpsData* makeGpsData(QString str);
	
	enum enumFixedStatus
	{
		ACTIVE, INVALID
	};
	
	enum enumLatHemisphere
	{
		NORTH, SOUTH
	};
	
	enum enumLonHemisphere
	{
		EAST, WEST
	};
	
	struct gpsData
	{
		//std::string commandWord;
		QString sCommandWord;
		float fDerivedTime;
		enum enumFixedStatus eFixedStatus;
		float fLatDecimalDegrees;
		enum enumLatHemisphere eLatHemisphere;
		float fLonDecimalDegrees;
		enum enumLatHemisphere eLonHemisphere;
		float fSpeed;
		float fBearing;
		QDate UTCdate;
		int iChkSum;
		
	};
	
	QString strFileContent;
	QString strFileName;
	QList <struct gpsData> listGpsData;
	
private slots:
	void FileOpen();
};
#endif

und mainwindowimpl.cpp
C++:
#include "mainwindowimpl.h"
//
MainWindowImpl::MainWindowImpl( QWidget * parent, Qt::WFlags f) 
	: QMainWindow(parent, f)
{
	setupUi(this);
	QObject::connect(butFileOpen, SIGNAL(clicked()), this, SLOT(FileOpen()));
}

void MainWindowImpl::FileOpen()
{
	strFileName = QFileDialog::getOpenFileName(this, "Select a GPS logfile");
	if(!strFileName.isEmpty())
	{
		QFile file(strFileName);
		if(file.open(QIODevice::ReadOnly | QIODevice::Text))
		{
			strFileContent = file.readAll();
			setFileText();
			setContentText();
		}
	}
	 
}

void MainWindowImpl::setFileText()
{
	txtFileContent->setText(strFileContent);
}

void MainWindowImpl::setContentText()
{
	struct gpsData* gps;
	
	int startLine = 0;
	for(int i = 0; i < strFileContent.length(); i++)
	{
		if(strFileContent[i] == '\n')
		{
			gps = makeGpsData(strFileContent.mid(startLine, i-1));
			startLine = i+1;
		}
	}
}

struct gpsData* MainWindowImpl::makeGpsData(QString str)
{
	struct gpsData* gps = new (struct gpsData);
	gps->sCommandWord = str;
	return gps;
}

Das Problem besteht nun darin, das innerhalb von makeGpsData ich die Struktur so nicht zurückgeben darf. Ich verstehe allerdings mal wieder nicht wieso ich das so nicht machen kann.
Hier vielleicht noch die Fehlermeldung die bekomme:
Code:
 src/mainwindowimpl.cpp: In member function »void MainWindowImpl::setContentText()«:
src/mainwindowimpl.cpp:40: Fehler: »gpsData*« kann nicht nach »MainWindowImpl::gpsData*« in assignment umgewandelt werden
src/mainwindowimpl.cpp: In member function »gpsData* MainWindowImpl::makeGpsData(QString)«:
src/mainwindowimpl.cpp:50: Fehler: »MainWindowImpl::gpsData*« kann nicht nach »gpsData*« in return umgewandelt werden

Beide Fehler scheinen ja die selbe Ursache zu haben.

Schon vorab vielen Dank!

Gruß
WingMan
 
Hi.

Erstmal hast du ja gar keine Referenz sondern einen ganz normalen Zeiger.

In C/C++ gibt es unvollständig definierte Typen, d.h. bei Zeigern ist es erlaubt das der Typ (struct, union) noch nicht vollständig definiert ist.

Bsp:
C++:
struct XYZ* foo; // OK, obwohl struct XYZ nicht definiert
Dann erlaubt es C++ Klassen und Strukturen innerhalb anderer Klassen zu definieren. Innerhalb des Klassen-Skopus kann man einfach drauf zugreifen, außerhalb muss man die Typen mit dem Klassennamen qualifizieren.

Was die Fehlermeldung besagt ist, dass du nicht einen Zeiger auf Typ X in einen Zeiger auf einen ganz anderen Typen Y konvertieren kannst. (gpsData und MainWindowImpl::gpsData sind nicht der gleiche Typ).

Das struct Schlüsselwort ist bei der Verwendung des Typs in C++ übrigens überflüssig, in C behilft man sich deshalb mit einem typedef.
C++:
MainWindowImpl::gpsData* MainWindowImpl::makeGpsData(QString str) {
  ...
}
Gruß
 
Guten morgen,

also wenn ich Deine Antwort richtig verstanden habe dann meintest Du ich solle es so umbauen:

mainwindowimpl.h:
C++:
#ifndef MAINWINDOWIMPL_H
#define MAINWINDOWIMPL_H
//
#include <iostream>
#include <string>
#include <QMainWindow>
#include <QFileDialog>
#include <QFile>
#include <QDate>
#include "ui_mainwindow.h"

using namespace std;
//
class MainWindowImpl : public QMainWindow, public Ui::MainWindow
{
Q_OBJECT
public:
	MainWindowImpl( QWidget * parent = 0, Qt::WFlags f = 0 );
	
	
//private:
	void setFileText();
	void setContentText();
	struct gpsData* makeGpsData(QString str);
	
	enum enumFixedStatus
	{
		ACTIVE, INVALID
	};
	
	enum enumLatHemisphere
	{
		NORTH, SOUTH
	};
	
	enum enumLonHemisphere
	{
		EAST, WEST
	};
	
	struct gpsData
	{
		//std::string commandWord;
		QString sCommandWord;
		float fDerivedTime;
		enum enumFixedStatus eFixedStatus;
		float fLatDecimalDegrees;
		enum enumLatHemisphere eLatHemisphere;
		float fLonDecimalDegrees;
		enum enumLatHemisphere eLonHemisphere;
		float fSpeed;
		float fBearing;
		QDate UTCdate;
		int iChkSum;
		
	};
	
	QString strFileContent;
	QString strFileName;
	QList <gpsData> listGpsData;
	
private slots:
	void FileOpen();
};
#endif

mainwindowimpl.cpp:
C++:
#include "mainwindowimpl.h"
//
MainWindowImpl::MainWindowImpl( QWidget * parent, Qt::WFlags f) 
	: QMainWindow(parent, f)
{
	setupUi(this);
	QObject::connect(butFileOpen, SIGNAL(clicked()), this, SLOT(FileOpen()));
}

void MainWindowImpl::FileOpen()
{
	strFileName = QFileDialog::getOpenFileName(this, "Select a GPS logfile");
	if(!strFileName.isEmpty())
	{
		QFile file(strFileName);
		if(file.open(QIODevice::ReadOnly | QIODevice::Text))
		{
			strFileContent = file.readAll();
			setFileText();
			setContentText();
		}
	}
	 
}

void MainWindowImpl::setFileText()
{
	txtFileContent->setText(strFileContent);
}

void MainWindowImpl::setContentText()
{
	MainWindowImpl::gpsData* gps;
	
	int startLine = 0;
	for(int i = 0; i < strFileContent.length(); i++)
	{
		if(strFileContent[i] == '\n')
		{
			gps = makeGpsData(strFileContent.mid(startLine, i-1));
			startLine = i+1;
		}
	}
}

MainWindowImpl::gpsData* MainWindowImpl::makeGpsData(QString str)
{
	MainWindowImpl::gpsData* gps = new MainWindowImpl::gpsData;
	gps->sCommandWord = str;
	return gps;
}
Er nöcketl aber immer noch :)
Code:
src/mainwindowimpl.cpp: In member function »void MainWindowImpl::setContentText()«:
src/mainwindowimpl.cpp:40: Fehler: »gpsData*« kann nicht nach »MainWindowImpl::gpsData*« in assignment umgewandelt werden
src/mainwindowimpl.cpp: At global scope:
src/mainwindowimpl.cpp:46: Fehler: Prototyp für »MainWindowImpl::gpsData* MainWindowImpl::makeGpsData(QString)« passt zu nichts in Klasse »MainWindowImpl«
src/mainwindowimpl.h:24: Fehler: Kandidat ist: gpsData* MainWindowImpl::makeGpsData(QString)

Wenn ich die Meldungen korrekt interpretiere passt ihm immer noch nicht die angebliche Konvertierung zwischen zwei unterschiedlichen structs und er findet keine Funktions-Deklaration zur Funktion makeGpsData().

Aber so wie ich Deine Antwort verstanden habe benötige ich doch in der Header Datei keinen Qualifizierer da sie sich im selben scope befinden, oder?

Verwirrend :confused:

Viele Grüße ein ratloser WingMan
 
Hi.

Die innere Struktur muss deklariert werden bevor du sie für Methodendeklarationen benutzt, sonst handelt es sich wieder um das gleiche Problem.

Gruß
 
Oops, mir war nicht bewusst das in C++ die Reihenfolge eine Rolle spielt (Java verwöhnt :) )

Wieder einmal: Danke, das hat geholfen

Gruß
WingMan
 
Hi, hier stellt sich vielleicht auch die Frage womit du die Deklaration der Struktur innerhalb der Klasse begründest. Ich definiere solche "Hilfsstrukturen bzw. komplexen Datentypen" immer außerhalb der Klasse. Kommt ja auch auf den Scope an, also wenn nur die Klasse davon wissen soll ist es berechtigt.

mfg ;)
 
Zurück