Komplilerfehler bei Dev C++ und Qt



  • Um mein DB-Tool besser verwalten zu können wollte ich mich in Qt mal einarbeiten um dafür eine Benutzeroberfläche zu schreiben, weit bin ich aber noch nicht gekommen, nach dem erzeugen der make dateien mit qmake spuckt er mir füt mich unerklärliche fehrmeldungen aus:

    Der code:

    Main.cpp

    #include <QApplication>
    #include <QLabel>
    #include "func1.h"
    #include "gui.h"
    
    int main(int argc, char *argv[]) {
        QApplication myApp(argc, argv);
        gui_main();
        return myApp.exec();
    }
    

    func1.h

    #include <QPushButton>
    #include <QObject>
    
    QWidget* myWidget;
    
    class newButton : public QPushButton
     {
         Q_OBJECT
    
     public:
         void fnewButton();
    
     signals:
         void buttonClicked();
    
     private:
         QPushButton *myButton;
    
     };
    
    void newButton::fnewButton(){
        myButton = new QPushButton(myWidget);
        connect(myButton, SIGNAL(clicked()),this, SIGNAL(buttonClicked()));
        myButton->setGeometry(10, 50, 120, 30);
        myButton->setText("test54321");
    }
    

    gui.h

    void gui_main() {
    
        QWidget* myWidget = new QWidget();
    
        myWidget->setGeometry(600, 450, 140, 140);
    
        QLabel* myLabel = new QLabel("Hallo Welt", myWidget);
        myLabel->resize(80, 30);
        myLabel->setGeometry(10, 10, 120, 30);
    
        QPushButton* myButton = new QPushButton("Button", myWidget);
        myButton->setGeometry(10, 30, 120, 30);
    
        newButton *vnewButton;
        vnewButton= new newButton;
        vnewButton->fnewButton();
    
        myWidget->show();
    }
    

    Folgende Fehlermeldungen werden beim Kompilieren ausgespuckt.

    multiple definition of `newButton::fnewButton()' 
      first defined here 
      multiple definition of `myWidget' 
      first defined here 
      ld returned 1 exit status 
     C:\bloodsheed\sim2\Makefile.Release [Build Error]  [release\sim2.exe] Error 1
    

    Ausser das mit unverständlich ist das der Button aus der Klasse nicht angezeigt wird (ich programmiere normalerweise reines ANSI C, weshalb ich auch will das die grafischen sachen ausserhalb meiner Main Funktion sind) funktioniert das Programm bissher fehlerfrei wenn ich das Q_OBJECT auskommetiere, erst wenn ich das Makefile von qmake mit Q_OBJECT benutze kommen diese Fehlermeldungen.
    Leider bin ich bis jetzt immernur auf den unützen komentar "kein sauberer stil" gestoßen und nicht auf hilfreiche komentare die mich weiterbringen. Desswegen wäre ich wirklich dankbar für ein lauffähiges Beispiel und einer Erklärung wo genau denn eigendlich das Problem liegt (nen guten Stil kann man sich auch nicht aneignen wenn man nichtmal zum Programmiern kommt).

    Der code stammt übrigens aus diversen online Dokus und ist einer meiner ersten ernsthafteren versuche mit c++.


  • Mod

    Also ich bin kein QT Experte, von daher verweise ich da mal auf andere.

    Aber, ich weiss das es für C++ (und gerade QT) bessere IDEs als Dev C++ gibt, ich würde dir also empfehlen, das du dir mal Code::Blocks, MSVC Express oder HaiQ ansiehst.



  • Ok, danke, werd mir die mal anschauen.
    Wäre aber trotzdem schön wenn sich jemand das nochmal genauer angucken könnte



  • alle implementierungen von funktionen müssen in einer cpp stehen. Wenn du den header in mehrere cpps einbindest, ist die funktion mehrfach implmentiert, das mag der linker nicht.

    Also: den funktionskörper von fnewButton() in eine cpp tun. Genau so ists mit dem QWidget* myWidget; Das muss auch in ein cpp rein. im header musst du dann schreiben:

    extern QWidget* myWidget;

    Allerdings sind solche globalen variablen meistens nicht gut und auch nich nötig



  • Ah, ok, danke, jetzt wird der code zumindest schonmal normal erstellt.
    Das mit den globalen variablen is mir auch ein begriff, das werd ich mir nochmal ansehen wenn ich mich besser mit klassen auskenn.

    Kann mir noch jemand sagen warum der button im funktionsaufruf der Klasse nicht angezeigt wird?


  • Mod

    seelenquell schrieb:

    Ah, ok, danke, jetzt wird der code zumindest schonmal normal erstellt.
    Das mit den globalen variablen is mir auch ein begriff, das werd ich mir nochmal ansehen wenn ich mich besser mit klassen auskenn.

    Kann mir noch jemand sagen warum der button im funktionsaufruf der Klasse nicht angezeigt wird?

    Weil du da die Globale Variable angibst, myWidget aber in der gui_func lokal ist.
    Vermeide generell globale Variablen, wenn du mit Klassen arbeitest, sie führen nur zu Fehlern und bringen nur wenig nutzen.
    Wenn du eine Klasse global verfügbar machen willst, wäre evtl. eine Configklasse als Singleton etwas für dich.



  • hrhr,
    das mit der lokalen definition hab ich glatt übersehen, dank dir.

    Naja, das mit den klassen is mir immernoch recht suspect.
    Naja, ich werd mich mal dransetzten und versuchen die als functionsparameter zu übergeben, dann hab ich das problem mit den Gültigkeitsbereichen netmehr.

    Was meinste denn mit "Configklasse als Singleton"? verstehh da ehrlichgesagt nur bahnhof.


  • Mod

    seelenquell schrieb:

    hrhr,
    das mit der lokalen definition hab ich glatt übersehen, dank dir.

    Naja, das mit den klassen is mir immernoch recht suspect.
    Naja, ich werd mich mal dransetzten und versuchen die als functionsparameter zu übergeben, dann hab ich das problem mit den Gültigkeitsbereichen netmehr.

    Was meinste denn mit "Configklasse als Singleton"? verstehh da ehrlichgesagt nur bahnhof.

    Als Funktionsparameter ist es auch besser. Singleton ist ein Designpattern, was sicherstellt, das es von einer Klasse nur eine Globale Instanz gibt.
    Aber wenn du noch neu in der OOP bist, solltest du dich vielleicht erstmal mit dem Konzept im Allgemeinen vertraut machen.



  • Jo, ich versuch mich grad in die OOP einzuarbeiten, leider funktioniert schon wieder was nicht. Den code hab ich wie folgt umgearbeitet:

    Main.cpp

    #include <QApplication>
    #include <QLabel>
    #include "MyFunc1.h"
    #include "gui.h"
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
        QApplication myApp(argc, argv);
        gui_main();
    
        //QObject::connect(myQuitButton, SIGNAL(clicked()), &myApp, SLOT(quit()));
        return myApp.exec();
    }
    

    gui.h

    void gui_main() {
    
        QWidget* MyWidget = new QWidget();
    
        MyWidget->setGeometry(600, 450, 140, 140);
    
        QLabel* myLabel = new QLabel("Hallo Welt", MyWidget);
        myLabel->resize(80, 30);
        myLabel->setGeometry(10, 10, 120, 30);
    
        QPushButton* myButton = new QPushButton("Button", MyWidget);
        myButton->setGeometry(10, 30, 120, 30);
    
        newButton *vnewButton;
        vnewButton= new newButton;
        //vnewButton->fnewButton();
    
        MyWidget=vnewButton->fnewButton(*MyWidget);
    
        MyWidget->show();
    }
    

    Myfunc.h

    #include <QFont>
    #include <QPushButton>
    #include <QObject>
    #ifndef MyFunc1_H 
    #define MyFunc1_H
    
    class newButton : public QPushButton
     {
         Q_OBJECT;
    
     public:
         QWidget fnewButton(QWidget MyWidget());
    
     signals:
         void buttonClicked();
    
     private:
         QPushButton *myButton;
    
     };
    #endif
    

    MyFunc.cpp

    #include "MyFunc1.h"
    
    QWidget newButton::fnewButton(QWidget MyWidget){
        myButton = new QPushButton(MyWidget);
        connect(myButton, SIGNAL(clicked()),this, SIGNAL(buttonClicked()));
        myButton->setGeometry(10, 50, 120, 30);
        myButton->setText("test54321");
    	return(MyWidget);
    }
    

    Folgende Fehlermeldungen werden dazu ausgespuckt:

    4 C:\bloodsheed\sim2\main.cpp In file included from main.cpp 
     C:\bloodsheed\sim2\gui.h In function `void gui_main()': 
    18 C:\bloodsheed\sim2\gui.h no matching function for call to `newButton::fnewButton(QWidget&)' 
     note C:\bloodsheed\sim2\MyFunc1.h:12 candidates are: QWidget newButton::fnewButton(QWidget (*)()) 
     note C:\bloodsheed\sim2\MyFunc1.h:12 candidates are: QWidget newButton::fnewButton(QWidget (*)())
    

    Die Fehlermeldungen beziehen sich dabei auf folgende Zeile:

    MyWidget=vnewButton->fnewButton(*MyWidget);
    

    Is mir ehrlich gesagt Zimlich rätzelhaft obwohl so im Buch steht.



  • Hab grad gesehen das sich beim bereinigen des quelltestes wohl nen fehler eingeschlichen hatte:
    Zeile 3 der Myfunc.cpp muss so lauten:

    QWidget newButton::fnewButton(QWidget MyWidget()){
    

    Das ändert allerding leider immernoch nichts daran das es immernoch nicht läuft


  • Mod

    Beschäftige dich doch erstmal mit den Grundlagen der OOP und von C++.

    Das Fenster solltest du am besten als Pointer übergeben, damit du es später nicht zurückgeben musst, was sowieso blödsinn ist, da du ja nur das Fenster verändern willst, es aber nicht erzeugst.



  • Und wie genau mach ich das? (codebeispiel wäre nicht schlecht)

    Was verstehtste denn genau unter grundlagen? in meinen Augen versuch ich grad genau das. Für konsolenanwendungen benutz ich mein C und genau wegen dem GUI sachen bin ich ja zum C++ gekommen und dotnet hat sich leider als verdammt lahm und ausserordentlich inkompatibel zu meinen bissherigen projekten rausgestellt.


  • Mod

    Versuch erstmal auf der Console C++ und OOP umzusetzen. Du brauchst dafür keine großen und komplizierten Frameworks wie QT.
    Später kannst du dann immer noch darauf aufbauen. Ein Anfang wäre sicherlich auch das C++ Magazin hier, da hat es einige gute Artikel.

    Und die Grundlagen für den Einstieg, ist dieses hier ganz gut:
    http://tutorial.schornboeck.net/



  • Für die konsolenprogrammierung kenn ich mich mit C gut genug aus, dafür brauch ich kein C++. ausserdem wüsste ich auch nicht was ich damit sinnvolles machen könnte.
    Zwei C++ bücher hab ich abgesehen davon schon hinter mir, ändert aber nichts daran das ich mich momentan mit oben genannten problem rumschlage. Da ist der Komentar das ich zuerst was anderes machen soll nicht grade hilfreich.
    Ich setz mich mit C++ auseinander weil ich eine benutzeroberfläche für ein existierendes Programm schreiben möchte, ohne benutzeroberfläche auch kein C++, warum soll ich mir die mühe machen für etwas das ich nicht gebrauchen kann.

    Also bitte ne direkte hilfe mit der exakten Problembehandlung wie es die vorherigen post auch gemacht haben, alles andere hilft mir nicht weiter, vor allen nicht den ganzen tag etwas zu lesen um dann festzustellen das es mich auch nicht weiterbringt. meist hängen so sachen einfach an kleinigkeiten wo man sich einfach festgefahren hat oder was auch immer und dann hilft auch nur ein schubs in die richtige richtung.


  • Mod

    Wenn du C so gut kannst, solltest du auch wissen was ein Pointer ist, und wie man ihn an eine Funktion/Methode übergibt.

    void foo::bar(myWidget* widget)
    {
      //tu was mit widget
    }
    

    phlox



  • Was ich in C kann reicht zumindest um das zu programmieren was ich eben damit programmiern will.

    phlox81 schrieb:

    void foo::bar(myWidget* widget)
    {
      //tu was mit widget
    }
    

    phlox

    Was genau soll ich damit anfangen? Ich weiß jetzt weder wo vorher mein Problem lag noch was ich mit dem Snipsel anfangen soll. Also bitte ne klare antwort die sich auf meinen Code bezieht damit ich genau nachvollziehen kann wo denn überhaupt das generelle Problem liegt. In allen büchern/tutorials steht das klassen so oder so ähnlich übergeben werrden wie ichs getan hab, ich hab dabei alle Kombinationen gestestet und keine hat das erwünschte resultat gebracht.
    Was also soll ich tun? Es komplett seinlassen oder um hilfe bitten und genau das tue ich hier und wenn ich das nicht generell falsch verstanden hab ist diese forum unter anderem genau dafür da. Also bitte wirf mir nich noch Steine in den Weg. Ich brauch ne klare und konkrete Antwort was denn nun genau der fehler ist, Autofahren lernt man auch nicht nur in den theoriestunden und ich häng auch nicht in der theorie sondern akut an der praksis.


  • Mod

    seelenquell schrieb:

    Was genau soll ich damit anfangen? Ich weiß jetzt weder wo vorher mein Problem lag noch was ich mit dem Snipsel anfangen soll. Also bitte ne klare antwort die sich auf meinen Code bezieht damit ich genau nachvollziehen kann wo denn überhaupt das generelle Problem liegt. In allen büchern/tutorials steht das klassen so oder so ähnlich übergeben werrden wie ichs getan hab, ich hab dabei alle Kombinationen gestestet und keine hat das erwünschte resultat gebracht.
    Was also soll ich tun? Es komplett seinlassen oder um hilfe bitten und genau das tue ich hier und wenn ich das nicht generell falsch verstanden hab ist diese forum unter anderem genau dafür da. Also bitte wirf mir nich noch Steine in den Weg. Ich brauch ne klare und konkrete Antwort was denn nun genau der fehler ist, Autofahren lernt man auch nicht nur in den theoriestunden und ich häng auch nicht in der theorie sondern akut an der praksis.

    Nun ja ich ging davon aus, das du aus C ja bereits Pointer kennen müsstest, und ebenfalls schon Funktionen verwendet hast.
    Dein Problem hier hat mit OOP erstmal nichts zu tun, du erstellst lediglich einige Objekte, und müsstest sie entsprechend an deine Methoden übergeben, und das macht man in C/C++ nun mal mit Pointern oder Referenzen.

    Und wenn sie so übergeben würden, müsste es ja kompilieren. Aber wie du schon selber festgestellt hast, tut es das nicht. Also muss es doch anders sein...
    Und eine Klasse kannst du nicht übergeben, zur Laufzeit existieren nur Objekte von Klassen, diese Instanzen kannst du dann übergeben etc.

    void newButton::fnewButton(mywidget* foo)
    

    Denke auf den Rest solltest du von alleine kommen.
    Du musst lediglich beim Aufruf der Methode den Pointer übergeben, welchen du ja schon in der GUI Methode hast.

    phlox



  • Nein, ehrlichgesagt versthe ich nicht was du von mir willst. Meiner meinung nach mach ich genau das, ich übergeb einen zeiger.
    Sag mir doch einfach was genau an meinem code geändert werden muss anstatt mir ständig neue codes um die ohren zu hauen mit denen ich nichts anzufangen weiß. wo kommt das foo auf einmal her? klar das er mir immer weitere fehlermeldungen auspuckt wenn ich versuch sowas einzubauen. natürlich weiß ich was nen zeiger ist und genau den versuch ich ja auch zu übergeben, aber ich weiß nicht wo im code denn genau das problem ist und was genau das problem ist.


  • Mod

    seelenquell schrieb:

    MyFunc.cpp

    #include "MyFunc1.h"
    
    QWidget newButton::fnewButton(QWidget MyWidget){
        myButton = new QPushButton(MyWidget);
        connect(myButton, SIGNAL(clicked()),this, SIGNAL(buttonClicked()));
        myButton->setGeometry(10, 50, 120, 30);
        myButton->setText("test54321");
    	return(MyWidget);
    }
    

    Folgende Fehlermeldungen werden dazu ausgespuckt:

    4 C:\bloodsheed\sim2\main.cpp In file included from main.cpp 
     C:\bloodsheed\sim2\gui.h In function `void gui_main()': 
    18 C:\bloodsheed\sim2\gui.h no matching function for call to `newButton::fnewButton(QWidget&)' 
     note C:\bloodsheed\sim2\MyFunc1.h:12 candidates are: QWidget newButton::fnewButton(QWidget (*)()) 
     note C:\bloodsheed\sim2\MyFunc1.h:12 candidates are: QWidget newButton::fnewButton(QWidget (*)())
    

    Die Fehlermeldungen beziehen sich dabei auf folgende Zeile:

    MyWidget=vnewButton->fnewButton(*MyWidget);
    

    Is mir ehrlich gesagt Zimlich rätzelhaft obwohl so im Buch steht.

    Du müsstest in fnewbutton einen Zeiger übergeben. So ist es eine normale Variable, die per copysemantic in die Funktion kommt.
    D.h. es wird eine neue Instanz für die Klasse gebildet, eine kopie. Das darf aber nicht sein, weil es ja nur ein Fenster geben soll.
    Ergo musst du die Variable von QWidget, mywidget, als Referenz oder Pointer übergeben.

    void newButton::fnewButton(QWidget* MyWidget)
    

    foo diente mir nur als Platzhalter.



  • Gut, wenn ich statt:

    MyWidget=vnewButton->fnewButton(*MyWidget);
    
    vnewButton->fnewButton(MyWidget);
    

    schreibe und

    QWidget newButton::fnewButton(QWidget* MyWidget)
    

    in

    void newButton::fnewButton(QWidget* MyWidget)
    

    ändere gehts wenn ich das return und die definition rausnehme. Wäre nett gewesen das auch so zu schreiben.

    Aber wenn ich mit absicht eine Kopie erstellen will (muss ja nicht zwingend nen widget sein), wie müssten dann die folgenden zeilen aussehen?

    MyWidget=vnewButton->fnewButton(*MyWidget);
    
    QWidget newButton::fnewButton(QWidget* MyWidget)
    
    return(MyWidget);
    

Anmelden zum Antworten