Vererbung funktioniert nicht



  • Danke dir! habe es jetzt hingekriegt, habe anstatt Auto:: halt Tesla:: und Audi:: vor die methoden geschrieben, und im header definiert ! so einfach und ich habe so lange gebraucht dafür DANKE!

    // Edit:
    Zu früh gefreut, es gibt jetzt keine compile fehler mehr.. aber wenn ich
    Auto* audi = new Audi; mache
    und daraufhin audi->fahren(), führt er die methode aus der Auto klasse aus und nicht aus der Audi klasse, aber genau die wollte ich ja überschreiben mithilfe der vererbung.

    //Edit 2:
    Okay scheint nun zu gehen. habe die voids in der Auto.h virtual gemacht



  • Ein Tipp: wenn du in Audi und Tesla sicherstellen willst, dass eine Funktion in Auto virtuell ist, dann deklarieren sie mit override . Dann bekommst du einen Compilefehler, wenn das virtual in Auto fehlt.

    Siehe http://en.cppreference.com/w/cpp/language/override



  • gerade ausprobiert danke für den hilfreichen tipp ! mal ne andere sache, gibt es in C++ wie in java eigl auch sowas wie packages ? (ordner für klassen)



  • In C++gibt es namespaces



  • Ich hätte es so gemacht:

    #include <iostream>
    #include <string>
    
    class IAuto
    {
    public:
        IAuto() {}
        virtual ~IAuto() {}
    
        virtual void start() = 0;
        virtual void fahren() = 0;
        virtual void stop() = 0;
    };
    
    class Tesla : public IAuto
    {
    public:
        Tesla()
        : IAuto()
        {}
    
        virtual ~Tesla()
        {}
    
        virtual void start()
        {
            std::cout << "Der Tesla macht brumm" << std::endl;
        }
    
        virtual void fahren()
        {
            std::cout << "Tesla fährt" << std::endl;
        }
    
        virtual void stop()
        {
            std::cout << "Der Tesla bleibt stehen" << std::endl;
        }
    
    };
    
    int main()
    {
        Tesla tesla;
        tesla.fahren();
    }
    

    Siehe https://en.wikibooks.org/wiki/C%2B%2B_Programming/Classes/Abstract_Classes
    Hat den Vorteil, dass man die Funktionen in IAuto implementieren MUSS, wenn man davon ableitet. Ähnlich dem Java "interface".

    Leftwitch2 schrieb:

    #pragma once
    #ifndef AUTO_H
    #define AUTO_H
    

    Hierzu noch: #pragma once reicht vollkomnmen. Das wird von allen gängigen Compilern unterstützt. Den altmodischen include guard kannst dir sparen, vor allem weil die gerne zu Fehlern führen, wegen Namenskollisonen mit anderen alten include guards.



  • gcc schrieb:

    CPP supports two more ways of indicating that a header file should be read only once. Neither one is as portable as a wrapper ‘#ifndef’ and we recommend you do not use them in new program

    https://gcc.gnu.org/onlinedocs/gcc-7.1.0/cpp/Alternatives-to-Wrapper-_0023ifndef.html#Alternatives-to-Wrapper-_0023ifndef



  • manni66 schrieb:

    gcc schrieb:

    CPP supports two more ways of indicating that a header file should be read only once. Neither one is as portable as a wrapper ‘#ifndef’ and we recommend you do not use them in new program

    https://gcc.gnu.org/onlinedocs/gcc-7.1.0/cpp/Alternatives-to-Wrapper-_0023ifndef.html#Alternatives-to-Wrapper-_0023ifndef

    Die Info auf der Seite ist veraltet. #pragma once wird von allen Compiler Suites bis auf die Portland Group C++ Suite. Den faktisch keiner hier benutzt. #import dagegen nur von gcc. Und wie ich schon sagte, sind include guards anfällig für namenskollisonen in der Form. Nur weil irgendwo was steht, heisst das nicht, dass es auch korrekt ist.

    Import ist in VC++ als Beispiel für .COM reserviert.

    https://msdn.microsoft.com/en-us/library/8etzzkb6(VS.71).aspx
    https://en.wikipedia.org/wiki/Pragma_once



  • gcc.gnu.org ist nicht irgendwo.



  • Ich frage mich bei Scorcher24s Code viel mehr, warum leere Konstuktoren und Destruktoren implementiert werden. Wenn man die nicht braucht, einfach weglassen.

    Natürlich muss der Destuktor ~IAuto virtual sein, aber ich würde dann vorschlagen, einfach folgendes zu schreiben:

    virtual ~IAuto() = default;
    

    Das macht deutlich klar, dass hier nichts benutzerdefiniertes stattfindet, sondern nur der Destruktor virtual gemacht wird.

    Und in den abgeleiteten Klassen wie Tesla eben nicht

    virtual void start()
    

    sondern

    void start() override
    

    Bzgl. Include-Guards:
    Was macht #pragma once eigentlich bei Symlinks, bei Hardlinks, bei Headern, die in unterschiedliche Verzeichnisse kopiert wurden? Mit normalen Include-Guards ist alles klar. Außerdem kann man dann auch mal einfach eine DummyClassAuto.h includen, die nur ein simples konstantes Auto modelliert - diese könnte dann das define für die "normale" Auto-Klasse enthalten und somit verhindern, dass diese geladen wird. Das ist dann zwar vielleicht "poor men's testing", aber mit pragma once hätte das nicht so einfach funktioniert.



  • wob schrieb:

    Bzgl. Include-Guards:
    Was macht #pragma once eigentlich bei Symlinks, bei Hardlinks, bei Headern, die in unterschiedliche Verzeichnisse kopiert wurden? Mit normalen Include-Guards ist alles klar. Außerdem kann man dann auch mal einfach eine DummyClassAuto.h includen, die nur ein simples konstantes Auto modelliert - diese könnte dann das define für die "normale" Auto-Klasse enthalten und somit verhindern, dass diese geladen wird. Das ist dann zwar vielleicht "poor men's testing", aber mit pragma once hätte das nicht so einfach funktioniert.

    Symlinks und ähnliches aufzulösen ist Aufgabe des Betriebssystems bzw Dateisystems. Auch bei Headern in unterschiedlichen Verzeichnissen gibt es da kein Problem. Ich verstehe nicht, wie du darauf kommst. Zudem haben include guards das Problem der Namenskollission. Wenn man sie benutzt, dann bitte mit Zufallszahlen drin. Aka

    #ifndef EXAMPLE_782376237623723_HPP
    #define EXAMPLE_782376237623723_HPP
    #endif
    

    Aber #import ist definitiv der falsche Weg und nicht halb so portabel wie pragma once.



  • Scorcher24 schrieb:

    Symlinks und ähnliches aufzulösen ist Aufgabe des Betriebssystems bzw Dateisystems.

    Aha. Komisch, dass es dann solche Fragen gibt: https://social.msdn.microsoft.com/Forums/SqlServer/en-US/f7d4aab9-c3b0-43a3-a51b-1a3fae87fcc7/pragma-once-and-symbolic-links?forum=vcgeneral

    Zu den unterschiedlichen Verzeichnissen (siehe https://en.wikipedia.org/wiki/Pragma_once#Caveats): "This backfires when the same file is intentionally copied into several parts of a project."



  • Wer macht den auch so ein scheiß mit symlinks? wtf?

    #pragma once macht viel weniger probleme als #ifndef etc.
    Vor allem sind versehentliche doppeltbenutzungen der macros oft nicht sehr offensichtliche Fehler.

    ...genauso wie leute die Pfade haben die MAX_PATH überschreiten und mit Sonderzeichen vollgeballert sind, nur weil die noch nie was von Datenbanken gehört haben... manche Leute wollen es auch wirklich wissen, wie man sich alles zerschießt!


Anmelden zum Antworten