Basisklasse undefiniert



  • Hallo

    und genau das ist der Grund für dein Problem gewesen.
    Du solltest immer so wenig wie nötig includen, vor allem in Headern selber. Auch mit Forward Declaration kann man sich machen Include sparen.
    Das hilft einerseits die Kompilierzeit zu senken, anderseits auch solche Kreis-Includes zu vermeiden.

    bis bald
    akari



  • heisst das ich hab recht?



  • Also Fachmann ich glaube du solltest nicht alle Dateien in deine *.h Datei includieren ^^ Genau das habe ich ja auch gemacht... 😃

    Frage mich gerade warum ich nicht gleich auf Scott Meyers gehört habe?
    Item 31: Minimize compilation dependencies between files.
    * Depend on class declarations instead of class definitions whenever you can.

    Includiert Ihr generell (die Ihr mehr Erfahrung habt als ich) keine (eigene) Header-Files (in *.h) sondern deklariert nur die Klasse? Kann man das generalisieren, oder gibt es Ausnahmen?

    Gruß,
    Chris



  • Hallo

    Includiert Ihr generell (die Ihr mehr Erfahrung habt als ich) keine (eigene) Header-Files (in *.h) sondern deklariert nur die Klasse? Kann man das generalisieren, oder gibt es Ausnahmen?

    Es gibt immer Ausnahmen. Die Forward Deklaration reicht wenn man nur einen Pointer oder Referenz braucht. Braucht man aber konkrete Instanzen oder will man von der Klasse ableiten, muß man die gesamte Deklaration kennen. Dann kommt man um einen Include im Header nicht umhin.

    bis bald
    akari



  • Danke Akari,

    klingt ziemlich logisch und macht Sinn. Gibt der scheinbar einfachen Definition des Includes aber einen faden Beigeschmack, weil der unerfahrene C++Coder durch einen Includekreis schnell mal in die Tischkannte beisst ...

    Ok, wie gesagt danke für die Einsichten! 👍



  • HolyGrail schrieb:

    ...Gibt der scheinbar einfachen Definition des Includes aber einen faden Beigeschmack, ...

    Naja, ich finde, es zwingt einen eben dazu, sich exakter Gedanken über Abhängigkeiten zu machen.
    ... und wenn man seine Abhängigkeiten nicht sauber in den Griff bekommt, beissen einen die viel später (und oft unangenehmer) ins Gesäß. 😉

    Gruß,

    Simon2.



  • Gedanken die ein Programmierer (meiner Meinung nach), aber besser in sein Softwaredesign stecken sollten, als in solche "Sprachdetails".

    --- Will jetzt aber keine Grundsatzdiskussion auslösen 🙄



  • HolyGrail schrieb:

    Gedanken die ein Programmierer (meiner Meinung nach), aber besser in sein Softwaredesign stecken sollten, als in solche "Sprachdetails"....

    Wenn er zu dem "Sprachdetail" kommt, ist aber die Designphase eigentlich schon vorbei - d.h. er tappt in die Falle, die er sich vorher selbst gelegt hat.
    Hat er eine saubere Abhängigkeitsdefinition designed, fällt ihm das include nicht in den Arm.... 😉

    ... ich weiß, dass das "Schönwetterflugtheorie" ist. 😃

    Gruß,

    Simon2.



  • Hi,
    ich hätte zu dem Thema auch noch ne Frage:
    http://www.sambalmueslie.de/test/Klassendiagramm.png
    So sieht meine Struktur aus.

    Jetzt steh ich vor dem Problem:

    1. Was wo includen?
    2. Wo eine Forward Deklaration

    Da die Klasse Framework alle anderen Klassen verwendet ist es da wohl eher sinnvol diese zu includen oder?

    In der Klasse Handler hab ich eine Forward-Deklaration auf Framework.

    #ifndef HANDLER_H_
    #define HANDLER_H_
    
    #include <iostream>
    using namespace std;
    
    #include "Object.h"
    #include "Framework.h"
    #include "HandlerInfo.h"
    #include "MSTEvent.h"
    #include "MSTMessage.h"
    
    //#define HANDLER_DEBUG 0
    class Framework;
    extern Framework *the_framework;
    
    class Handler : public Object
    {
    public:
    	Handler();
    	Handler(Handler & rhs);
    	~Handler();
    
    	HandlerInfo& getHandlerInfo();
    	int getHandlerStatus();
    
    	virtual void reciveEvent(MSTEvent* event);
    	virtual void sendEvent(MSTEvent* event);
    	virtual void sendMessage(MSTMessage* message);
    	virtual void output(ostream& os);
    	virtual void operator=(Handler & rhs);
    	friend ostream& operator << (ostream& os, Handler& op);
    
    private:
    	int handler_id;
    	int handler_status;
    	HandlerInfo handler_info;
    };
    
    #endif /*HANDLER_H_*/
    

    jetzt meckert mir halt der Compiler bei

    void Handler::sendMessage(MSTMessage * message)
    {
    #ifdef HANDLER_DEBUG
    	cout << __PRETTY_FUNCTION__ << endl;
    #endif
    	the_framework->writeMessage(message);
    }
    

    no matching function for call to ‘Framework::writeMessage(MSTMessage*&)’ MCX_Software_Test_V_0_4_1/MST_Framework/Handler Handler.cpp line 60

    Was mir auch logisch erscheint.
    Doch wie bekomme ich das weg??

    Grüßle Oli



  • Wie gesagt, inkludiere so wenig wie nötig.
    D.h. entferne erst mal alle Includes und ersetze sie durch Vorwärtsreferenzen...
    (außer "object.h", da du ja davon ableitest sowie "HandlerInfo.h", da du davon ein Member erzeugst)

    Selbst <iostream> kannst du durch <iosfwd> ersetzen (Forward references).

    Nur in den Source-Dateien brauchst du dann die includes...

    und vor allem:
    Verwende NIEMALS "using namespace std;" in Header-Dateien!!!



  • Th schrieb:

    Wie gesagt, inkludiere so wenig wie nötig.
    D.h. entferne erst mal alle Includes und ersetze sie durch Vorwärtsreferenzen...
    (außer "object.h", da du ja davon ableitest sowie "HandlerInfo.h", da du davon ein Member erzeugst)

    Selbst <iostream> kannst du durch <iosfwd> ersetzen (Forward references).

    Nur in den Source-Dateien brauchst du dann die includes...

    und vor allem:
    Verwende NIEMALS "using namespace std;" in Header-Dateien!!!

    Oki ich versuchs mal, kleine Frage am Rande noch, was sind den Vorwärtsreferenzen??
    Grüßle Oli



  • class Framework; // Vorwärtsreferenz (Forward Reference)
    


  • Th schrieb:

    class Framework; // Vorwärtsreferenz (Forward Reference)
    

    Ah ok.. thx..



  • ich halte es immer so, dass es eine zentrale headerfile gibt in der alle anderen header included werden. alle .cpp-dateien inkludieren *ausschließlich* diesen header.
    header-files (mit ausnahme des zentralen) inkludieren in diesem modell in der regel keine anderen header.

    dadruch werden alle cpp-dateien von allen headern abhängig. jede header-änderung führt deshalb dazu, dass alle files neu kompiliert werden müssen. allerdings hat das auch einen großen vorteil: visual c++ kann precompiled header nur so mit maximaler effizienz verwenden, was die kompilierungsgeschwindigkeit teilweise enorm steigert.
    ich hab früher auch immer darauf geachtet, abhängigkeiten wo immer möglich zu vermeiden. im endeffekt bringts aber nix ausser zusätzlicher arbeit. die precompiled header machen die zusätzlichen abhängkeiten eigentlich immer mehr als wett.
    ein projekt, umgestellt auf dieses modell, kompilierte nachher mehr als 10 mal so schnell.



  • HolyGrail schrieb:

    Includiert Ihr generell (die Ihr mehr Erfahrung habt als ich) keine (eigene) Header-Files (in *.h) sondern deklariert nur die Klasse? Kann man das generalisieren, oder gibt es Ausnahmen?

    Kurz gesprochen: Includiere was nötig ist, Deklariere was möglich ist 😉

    Sofern ich Includes vermeiden kann, mache ich das auch (Sprich sofern nur Pointer oder Referenzen im Header verwendet werden: Vorwärtsdeklaration; sonst include). Dies hat mehrere Vorteile, einer davon ist die reduzierte Compilezeit 😉

    cu André



  • inkluda schrieb:

    ...eine zentrale headerfile gibt in der alle anderen header included werden. alle .cpp-dateien inkludieren *ausschließlich* diesen header...

    Dies halte ich nicht nur für ein sehr schlechtes Design, das ist auch eben dieses:

    inkluda schrieb:

    dadruch werden alle cpp-dateien von allen headern abhängig.

    Eben darum...

    inkluda schrieb:

    jede header-änderung führt deshalb dazu, dass alle files neu kompiliert werden müssen. allerdings hat das auch einen großen vorteil: visual c++ kann precompiled header nur so mit maximaler effizienz verwenden, was die kompilierungsgeschwindigkeit teilweise enorm steigert.

    Die Nachteile überwiegen aber:
    1. Der Precompiled Header ist nicht ANSI C++ Standard
    2. Die Kompilierungsgeschwindigkeit wird dadurch nur zu einen bestimmten Grad erhöht, bei großen Projekten kann genau das Gegenteil der Fall sein. Der Precompiled Header sollte wenn man ihn schon verwendet nur das enthalten was tatsächlich möglichst nie geändert wird
    3. Warum umbedingt bei einer kleinen Änderung alles neu linken müssen?

    Es ist meines Erachtens immer besser die Abhängigkeiten zu minimieren (grade wenn bestimmte Dateien von mehreren Projektteilen verwendet werden), dadurch sinkt der Linkaufwand ohnehin schon erheblich, und es wird immer nur dort etwas neu gelinkt wo es unbedingt notwendig ist.

    Ich persönlich bin aber schon aus einem anderen Grund gegen Precompiled Header: Wenn du mit unterschiedlichen Compilern arbeitest die entweder teilweise ohne Precompiled Header arbeiten, oder mit fixen (unterschiedlichen) Namen, kann das dazu führen das du, falls man Header in mehreren Projekten benutzt du immer noch irgendwelche "Dummydateien" hinzufügen musst damit der Compiler xyz glücklich wird...

    Warum abhängigkeiten überhaupt maximieren, und nicht einfach durch ein sauberes Design die Linkzeit reduzieren und Probleme vermeiden?

    cu André



  • asc schrieb:

    1. Der Precompiled Header ist nicht ANSI C++ Standard

    aha. und? wenn ich auf meiner zielplattform mein projekt 10x schneller kompilieren kann ist mir das ziemlich egal.
    außerdem spielt es keine rolle, weil es für andere compiler transparent ist. entweder sie werden angelegt und genutzt oder nicht. kompilieren tuts in jedem fall.

    2. Die Kompilierungsgeschwindigkeit wird dadurch nur zu einen bestimmten Grad erhöht, bei großen Projekten kann genau das Gegenteil der Fall sein.

    ist mir aber noch nie passiert und ich arbeite an relativ großen projekten (eines davon ~600k LOC)

    3. Warum umbedingt bei einer kleinen Änderung alles neu linken müssen?

    visual c++ kompiliert mit den richtigen header-einstellungen 100 dateien in der gleichen zeit wie es ohne precompiled header nur 10 dateien schafft (schätzung, ich hab die zeit nicht gemessen). da ist der break-even schnell erreicht.
    natürlich gibt es szenarien, in denen es ohne ph vielleicht kurzfristig schneller ginge (z.b. tweaking von irgendwelchen werten im header einer basisbibliothek).

    Warum abhängigkeiten überhaupt maximieren, und nicht einfach durch ein sauberes Design die Linkzeit reduzieren und Probleme vermeiden?

    ich bin bisher bei großen projekten mit meinem ansatz gut gefahren und in jedem projekt in das ich eingestiegen bin, wurde mir mir bessere effizienz bescheinigt, nachdem ein projekt von deinem modell auf meins umgestellt wurde.
    zugegebenermaßen waren mehrere unterschiedliche compiler dabei nie ein thema.

    theoretisch mag dein ansatz der sauberere sein, in der praxis fährt man meiner erfahrung nach besser mit meinem ansatz. ich habe vor ein paar jahren noch den gleichen standpunkt wie du vehement vertreten, wurde aber zwischenzeitlich eines besseren belehrt.



  • inkluda schrieb:

    3. Warum umbedingt bei einer kleinen Änderung alles neu linken müssen?

    visual c++ kompiliert mit den richtigen header-einstellungen 100 dateien in der gleichen zeit wie es ohne precompiled header nur 10 dateien schafft (schätzung, ich hab die zeit nicht gemessen). da ist der break-even schnell erreicht.
    natürlich gibt es szenarien, in denen es ohne ph vielleicht kurzfristig schneller ginge (z.b. tweaking von irgendwelchen werten im header einer basisbibliothek).

    Das gilt aber afaik nur, wenn der präcompilte Header halbwegs stabil ist - wenn sich dort ständig etwas ändert, hast du ein Problem: Statt nur die 2 Quellfiles neu zu compilieren, die wirklich etwas mit der Änderung zu tun haben, mußt du alle Quelldateien des Projekts neu compilieren.

    (PS: Wie groß sind denn die Projekte, die du üblicherweise bearbeitest?)



  • (PS: Wie groß sind denn die Projekte, die du üblicherweise bearbeitest?)

    multimedia-projekte, auch spiele, im bereich von 100k bis 1mio loc.
    was noch dazu gesagt werden muss: natürlich hängen dabei nicht alle dateien im gleichen .vcproj, sondern sind normalerweise auf verschiedene libs verteilt, die unabhängig voneinander kompiliert werden. wenn man ein einzelnes makefile mit 3000 files hat, geht die rechnung wahrscheinlich nicht mehr auf.



  • inkluda schrieb:

    (PS: Wie groß sind denn die Projekte, die du üblicherweise bearbeitest?)

    multimedia-projekte, auch spiele, im bereich von 100k bis 1mio loc.

    Und wieviele Klassen sind daran beteiligt?

    (btw, wenn du alle Klassenheader in die "stdafx.h" reinpackst, mußt du auch wieder auf die Reihenfolge achten)


Anmelden zum Antworten