Eine Instanz einer Klasse in einer anderen Klasse aufrufen
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Da ich QT benutze ist es mir nicht möglich
ServerSys
in der KlasseServerNet
zu erstellen, oder andersrum. alle Instanzen müssen leider in derMain.cpp
erstellt werden.Also das müsstest du mal näher erklären. Ich benutze auch viel QT und musste noch nie irgendwas zwangsläufig in der main.cpp machen.
Nutzt du eigentlich das QT-Framework oder einfach nur den QTCreator als Entwicklungsumgebung? In deinem Quellcode ist jetzt von QT selber nix zu sehen.
-
Also wenn ich versuche
ServerSys serverSys
in meiner Funktion in derServerNet
Klasse zu schreiben, kommt der Fehler:QWidget: Must construct a QApplication before a QWidget
. Keine Ahnung was das heißt, im Internet finde ich keine Lösung, passend zu meinem Problem dafür. Hättest du eine Lösung für diesen Fehler?
Ich benutze das QT-Framework, allerdings habe ich den Code für die Übersichtlichkeit auf das Wesentliche reduziert, weil dieser sonst viel zu lang wäre.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
auf das Wesentliche reduziert
Nein du hast ihn bis zur unkenntlichkeit kastriert und dann das eigentliche Problem für dich behalten.
Die Fehlermeldung sagt es schon: es muss zuerst ein QApplicationobject existieren, bevor GUI-Objekte instanziiert werden können. Die Riehenfolge ist entscheiden, nicht der Ort.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Hättest du eine Lösung für diesen Fehler?
Wie soll man den Qt-Fehler finden ohne qt-code?
Aber Tipp ohne code: Du hast halt wahrscheinlich irgendwo ein globales QWidget.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Also wenn ich versuche
ServerSys serverSys
in meiner Funktion in derServerNet
Klasse zu schreiben, kommt der Fehler:QWidget: Must construct a QApplication before a QWidget
. Keine Ahnung was das heißt, im Internet finde ich keine Lösung, passend zu meinem Problem dafür. Hättest du eine Lösung für diesen Fehler?
Ich benutze das QT-Framework, allerdings habe ich den Code für die Übersichtlichkeit auf das Wesentliche reduziert, weil dieser sonst viel zu lang wäre.Du willst eine QT-Anwendung bauen ( ein Frontend ? ) und hast aber keine QApplication-Instanz erzeugt, die dafür notwendig ist. Du hast also in Wirklichkeit ein ganz anderes Problem: Du hast irgendwas gemacht ohne wirklich zu wissen was du tust.
Also meine QT-Frontends sehen alle irgendwie so oder so ähnlich aus:
int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
Desweiteren gilt immer:
Trennung von Datenhaltung und Visualisierung!
D.h. deine Visualisierung ( was wohl ServerSys ist? ) sollte niemals teil der Datenhaltung ( ServerNet ) sein. Beide sind im Grunde voneinander unabjängige Objekte und sollten maximal mit einander kommunizieren, aber trotzdem räumlich getrennt. ( Kommunikation in QT: Signals und Slots ).Desweiteren empfiehlt es sich, den Klassen sprechende Namen zu geben. In einem Jahr weißt du doch nicht mehr ansatzweise, wofür ServerNet gut ist und wofür ServerSys gut ist.
-
Hier ist mein Code:
Main.cpp
#include "ServerSys.hpp" #include "ServerNet.hpp" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); ServerNet serverNet; ServerSys serverSys; serverSys.show(); return a.exec(); }
ServerNet.cpp:
#include "ServerNet.hpp" #include "ServerSys.hpp" #include <string> #include <iostream> #include <QTcpServer> #include <QTcpSocket> #include <unistd.h> #include <QApplication> static QTcpSocket *socket; ServerNet::ServerNet(QObject *parent) : QObject(parent) { server = new QTcpServer(this); connect(server, SIGNAL(newConnection()), this, SLOT(newConnection())); server->listen(QHostAddress::Any, 1234); } void ServerNet::newConnection() { socket = server->nextPendingConnection(); receiveRequest(); } void ServerNet::receiveRequest() { std::string receivedRequest; socket->waitForReadyRead(2000); receivedRequest = socket->readAll().toStdString(); if(receivedRequest == "label270") { //Hier entsteht wahrscheinlich das Problem ServerSys serverSys; serverSys.sendData(); } else { std::cout << "No valid data request" << std::endl; exit(1); } } void ServerNet::sendData(long long decLabel) { socket->write(std::to_string(decLabel).c_str()); }
ServerSys.cpp:
#include "ServerSys.hpp" #include "ui_ServerSys.h" #include "ServerNet.hpp" #include <iostream> #include <iomanip> #include <sstream> #include <math.h> #include <algorithm> #include <vector> #include <string> #include <QDesktopWidget> ServerSys::ServerSys(QWidget *parent) : QMainWindow(parent), ui(new Ui::ServerSys) { ui->setupUi(this); } ServerSys::~ServerSys() { delete ui; } void ServerSys::sendData() { std::vector<long long> decTokens(8); std::vector<std::string> binTokens(8); std::vector<bool> binLabel; long long decLabel; getData(decTokens); calculateDecToBin(decTokens, binTokens); fillBinValues(binTokens); combineBinValues(binTokens, binLabel); calculateBinToDec(binLabel, decLabel); //Hier entsteht wahrscheinlich das Problem ServerNet serverNet; serverNet.sendData(decLabel); } void ServerSys::getData(std::vector<long long> &decTokens) { //Hier kommt nichts beim Output heraus, da ich wahrscheinlich mehrere Instanzen der Klasse ServerSys habe, obwohl //ich etwas wie 12345 in das Textfeld schreibe. std::cout << ui->lineEdit_label_270->text().toStdString() << std::endl; decTokens[0] = ui->lineEdit_label_270->text().toLongLong(); decTokens[1] = ui->lineEdit_sdi_270->text().toLongLong(); decTokens[2] = ui->lineEdit_distance_270->text().toLongLong(); decTokens[3] = ui->lineEdit_lsb_270->text().toLongLong(); decTokens[4] = ui->lineEdit_msb_270->text().toLongLong(); decTokens[5] = 0; decTokens[6] = ui->lineEdit_ssm_270->text().toLongLong(); decTokens[7] = ui->lineEdit_parity_270->text().toLongLong(); } void ServerSys::calculateDecToBin(std::vector<long long> &decTokens, std::vector<std::string> &binTokens) { //Berechnungen... } void ServerSys::fillBinValues(std::vector<std::string> &binTokens) { //Berechnungen.... } void ServerSys::combineBinValues(std::vector<std::string> &binTokens, std::vector<bool> &binLabel) { //Berechnungen... } void ServerSys::calculateBinToDec(std::vector<bool> &binLabel, long long &decLabel) { //Berechnungen... }
Also meiner Meinung nach löse ich das Problem, dass ich in
ServerSys.cpp
keinen Output bekomme damit, wenn ich es schaffe nur mit jeweils einer Instanz zu arbeiten. Aber ich weis leider nicht, wie ich das schaffe.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Also meiner Meinung nach löse ich das Problem, dass ich in ServerSys.cpp keinen Output bekomme
Jetzt gibt es also schon wieder ein anderes Problem?
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Also meiner Meinung nach löse ich das Problem, dass ich in
ServerSys.cpp
keinen Output bekomme damit, wenn ich es schaffe nur mit jeweils einer Instanz zu arbeiten. Aber ich weis leider nicht, wie ich das schaffe.Ich glaube, die meisten sind hier verwirrt, was eigentlich genau das Problem ist. Ich fürchte du kommst hier nicht drumherum etwas ins Detail zu gehen und genau zu sagen, was wo nicht funktioniert/kompiliert, etc.
PS: wenn ServerSys eigentlich ein Window oder Dialog ist, dann tue dir selbst und allen Lesenden doch einfach den Gefallen und gib der Klasse einen entsprechenden Namen, einfach um Verwirrung zu vermeiden.
Warum ist
static QTcpSocket *socket
eigentlich static?
Der socket wird in der Klasse ServerNet verwendet um die neue Connection zu bespielen. reicht das nicht, wenn der Socket nur in der Klasse bekannt ist?
Was passiert, wenn mehrere neue Connections reinkommen?
-
@manni66
Nein, aber ein anderes Problem, wie ich einen richtigen Output bekomme, löst sich meiner Meinung nach damit, das Problem mit den Instanzen, wie in diesem Post beschrieben, zu lösen.
Also das Problem bleibt bei den Instanzen. ^^
-
@It0101 @manni66
Sorry für die Verwirrung. Werde das in meinem nächsten Post besser machen
Also das Problem, dass ich hab bleibt bei den Instanzen. Nur durch die Lösung dieses Problems lässt sich widerrum ein anderes Problem lösen, aber darum geht meine Frage auch nicht.Um näher ins Detail zu gehen:
In der Main.cpp erstelle ich die Instanz von ServerNet und ServerSys. Diese müssen sich aber gegenseitig in dessen Sourcecode ansprechen. Also zum Beispiel inServerSys
mitserverNet.funktion()
und inServerNet
mitserverSys.funktion()
.
Ich weis allerdings nicht, wie ich diese untereinander ansprechen kann, ohne nicht eine neue Instanz zu erstellen, so wie ich es bis jetzt inServerNet.cpp
in Zeile33
, oder inServerSys
in Zeile37
tue. Es müssen die Instanzen angesprochen werden, die in derMain.cpp
erstellt wurden.
-
Interne Klassen (bzw. deren Instanzen) sollten direkt keinen Zugriff auf UI-Elemente haben.
Auch das Anlegen der
ServerNet
-Variable in dermain
ist sinnfrei, solange du sie nicht dem UI-ElementServerSys
bekanntmachst (also z.B. per Referenz als Konstruktorparameter:ServerSys(ServerNet &serverNet)
und dann als Referenz-Member ablegst - oder aber sie gleich direkt als Member anlegst).Und in der
ServerSys
-Klasse greifst du dann nur auf diesen Member zu (anstatt neueServerNet
-Instanzen dort anzulegen).Und in der
ServerNet
-Instanz entkoppelst du den Zugriff auf die UI, indem du ein Signal erstellst, welches dann von derServerSys
-Instanz als Slot entgegengenommen wird (Stichwort: ereignisorientiert).
-
@Th69 sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Interne Klassen (bzw. deren Instanzen) sollten direkt keinen Zugriff auf UI-Elemente haben.
Auch das Anlegen der
ServerNet
-Variable in dermain
ist sinnfrei, solange du sie nicht dem UI-ElementServerSys
bekanntmachst (also z.B. per Referenz als Konstruktorparameter:ServerSys(ServerNet &serverNet)
und dann als Referenz-Member ablegst - oder aber sie gleich direkt als Member anlegst).Und in der
ServerSys
-Klasse greifst du dann nur auf diesen Member zu (anstatt neueServerNet
-Instanzen dort anzulegen).Und in der
ServerNet
-Instanz entkoppelst du den Zugriff auf die UI, indem du ein Signal erstellst, welches dann von derServerSys
-Instanz als Slot entgegengenommen wird (Stichwort: ereignisorientiert).this!
Es ist auch kein Problem, dass ServerNet ein Member von ServerSys(Window) ist.
ServerSys DARF ServerNet kennen. Nur andersherum nicht.
Wenn du aus ServerNet Informationen rausholen willst:- Signal in ServerNet einbauen. Slot in ServerSys. Beides verbinden.
- GetterFunktion in ServerNet einbauen, die von ServerSys aus aufgerufen wird
-
Ich habe es mit
this
in ServerNet.cpp versucht:void ServerNet::receiveRequest() { std::string receivedRequest; socket->waitForReadyRead(2000); receivedRequest = socket->readAll().toStdString(); if(receivedRequest == "label270") { ServerSys serverSys; serverSys.sendData(this); } else { std::cout << "No valid data request" << std::endl; exit(1); } }
Ich habe es mit einem Getter in ServerNet.cpp versucht:
ServerNet ServerNet::getServerNet() { return *this; }
Allerdings bekomme ich bei jedem
this
den Fehler:ServerNet.cpp:33:28: error: copying parameter of type 'ServerNet' invokes deleted constructor ServerNet.hpp:9:19: note: copy constructor of 'ServerNet' is implicitly deleted because base class 'QObject' has a deleted copy constructor qobject.h:467:20: note: 'QObject' has been explicitly marked deleted here
Keine Ahnung, was ich dagegen machen kann. Weist du noch was?
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
Allerdings bekomme ich bei jedem this den Fehler:
Nein.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
QObjects haben keinen öffentlichen Copy Constructor oder Assignment Operator. Du kannst aber einen Pointer auf das Objekt zurück geben:
ServerNet* ServerNet::getServerNet() { return this; }
-
@Coop4Free bist du sicher, dass du dich schon an Sockets und QT-Frameworks heranwagen willst?
Aus meiner Sicht bist du einfach noch nicht soweit.
-
@Coop4Free sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:
ServerSys serverSys; serverSys.sendData(this);
Das ist weiterhin falsch!
Edit: Hast du etwa
@It0101 sagte in Eine Instanz einer Klasse in einer anderen Klasse aufrufen:this!
falsch verstanden??? Damit hat @It0101 nur seine Bestätigung ausgedrückt.
LOL
-
Ich habe es mit beiden von dir vorgeschlagenen Lösungen versucht, aber egal was ich versuche, ich bekomme es einfach nicht hin. Vermutlich nicht, weil deine Lösungsvorschläge falsch sind, sondern weil ich sie nur falsch umsetze und andauernd gibt es irgendwelche Fehler.
Da ich es für meine Arbeit brauche, muss ich es tun, ob ich dem Thema gewachsen bin, oder nicht.Könntest du mir bitte ein Codebeispiel für deine Lösungen schreiben? Das wäre sehr hilfreich.
-
Am besten du postest mal deinen grundlegenden Aufbau, ohne Inhalt. D.h. wer kennt wen, wer besitzt wen, wer ist mit wem über welchen Slot verbunden.
Nur Klassen und Funktionshüllen mal zeigen. Inhalt ist uninteressant, denn du hast ein strukturelles Problem, selbst wenn man mal ausnahmsweise außen vor lässt, dass du versuchst QObjects zu kopieren.
-
Das wäre wohl ersteinmal das beste, wobei Fehleranalyse und -behebung zu den wichtigsten Fähigkeiten eines (Software-)Entwicklers gehört.