Basisklasse undefiniert



  • 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)



  • CStoll schrieb:

    Und wieviele Klassen sind daran beteiligt?

    uff, nie gezählt. wenn ich das aktuelle (halbfertige) projekt anschaue: 1084 .cpp und .h dateien, also geschätzte 550 bis 600 klassen.

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

    weiß nicht ob stdafx.h irgendwelche besonderen anforderungen hat. ich habe eine solche datei nicht in meinen projekten, weil ich alles von hand einstelle ohne assistenten.
    generell muss man natürlich die abhängigkeiten der header untereinander beachten, was sich in der reihenfolge im master-header niederschlägt.



  • inkluda schrieb:

    uff, nie gezählt. wenn ich das aktuelle (halbfertige) projekt anschaue: 1084 .cpp und .h dateien, also geschätzte 550 bis 600 klassen.

    ...aufgeteilt in 12 subprojekte.



  • inkluda schrieb:

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

    weiß nicht ob stdafx.h irgendwelche besonderen anforderungen hat. ich habe eine solche datei nicht in meinen projekten, weil ich alles von hand einstelle ohne assistenten.
    generell muss man natürlich die abhängigkeiten der header untereinander beachten, was sich in der reihenfolge im master-header niederschlägt.

    Genau das meinte ich ("stdafx.h" ist der Default-Name, den VS dem präcompiled Header verpasst). Und imho ist es wesentlich schwieriger, die Reihenfolge der Header dort aktuell zu halten als wenn du überall genau die Header einbindest, die du benötigst. (das ergibt schon genug Abhängigkeiten zwischen den einzelnen Klassen)

    (in einen gemeinsamen Master-Header oder Precompiled Header sollten nur Sachen rein, von denen du weißt, daß sie auf absehbare Zeit nicht angefasst werden - und die vom gesamten Projekt benötigt werden (z.B. AFX-Header))



  • CStoll schrieb:

    (in einen gemeinsamen Master-Header oder Precompiled Header sollten nur Sachen rein, von denen du weißt, daß sie auf absehbare Zeit nicht angefasst werden - und die vom gesamten Projekt benötigt werden (z.B. AFX-Header))

    wie soll das aussehen? wenn man precompiled header verwendet, darf man doch im .cpp nichts anderes includieren außer den master header (sonst "precompiled header directive not found"). außer vielleicht in diesem "use precompiled header automatically"-modus, der allerdings auch ein gutes stück langsamer ist als es konsequent durchzuziehen.

    CStoll schrieb:

    Und imho ist es wesentlich schwieriger, die Reihenfolge der Header dort aktuell zu halten als wenn du überall genau die Header einbindest, die du benötigst.

    wenn das projekt von anfang an so aufgebaut ist, muss man neue header einfach nur an der richtigen stelle einfügen. wir hatten damit bisher noch nie probleme.
    existierende projekte so umzubauen ist natürlich aufwendiger, aber man muss es ja nur einmal machen.



  • inkluda schrieb:

    CStoll schrieb:

    (in einen gemeinsamen Master-Header oder Precompiled Header sollten nur Sachen rein, von denen du weißt, daß sie auf absehbare Zeit nicht angefasst werden - und die vom gesamten Projekt benötigt werden (z.B. AFX-Header))

    wie soll das aussehen? wenn man precompiled header verwendet, darf man doch im .cpp nichts anderes includieren außer den master header (sonst "precompiled header directive not found"). außer vielleicht in diesem "use precompiled header automatically"-modus, der allerdings auch ein gutes stück langsamer ist als es konsequent durchzuziehen.

    Wenn du precompiled Header verwendet, darf nichts vor dem #include "stdafx.h" stehen - dahinter sind andere Header erlaubt.

    CStoll schrieb:

    Und imho ist es wesentlich schwieriger, die Reihenfolge der Header dort aktuell zu halten als wenn du überall genau die Header einbindest, die du benötigst.

    wenn das projekt von anfang an so aufgebaut ist, muss man neue header einfach nur an der richtigen stelle einfügen. wir hatten damit bisher noch nie probleme.
    existierende projekte so umzubauen ist natürlich aufwendiger, aber man muss es ja nur einmal machen.

    Und was, wenn du erst im Nachhinein feststellst, daß sich zwei gegebene Klassen doch brauchen?

    (außerdem bleibt noch immer das Problem der unnötigen Abhängigkeiten - wenn du zu irgendeiner Klasse den Header änderst, mußt du dein gesamtes Projekt neu compilieren, weil JEDE andere Klasse diesen Header (indirekt) einbindet - bei mir müssen nur die Klassen neu durch den Compiler, die etwas mit der geänderten Klasse zu tun haben)



  • inkluda schrieb:

    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....

    Ich denke, Du übersiehst, dass "Abhängigkeit" kein technisches Problem ist, sondern ein fachliches. Und dieses fachliche Problem schaffst Du Dir mit einer technischen Maßnahme....

    Spätestens wenn Du Deine Sourcen mehrfach verwendest (in unterschiedlichen Versionen oder Projekten), schießt Du Dir mit dieser Vorgehensweise übelst ins Knie.
    Z.B. ein ganz normales Szenario:

    Utilities:
    ----------
    Module (includieren jeweils all_headers.h):
    - ausgabe.cpp
    - simulation.cpp
    - kommunikation.cpp
    Header:
    - ausgabe.h
    - simulation.h
    - kommunikation.h
    - all_headers.h (includieren ausgabe.h, simulation.h und kommunikation.h)
    
    Produkt X:
    ---------
    Modul:
    - xKram.cpp 
    includiert: all_headers.h
    linkt: ausgabe.cpp, simulation.cpp
    
    Produkt Y:
    ---------
    Modul
    - yKram.cpp      
    includiert: all_headers.h
    linkt: kommunikation.cpp
    
    • Produkte X und Y sind bereits an jeweils 20 Kunden ausgeliefert und in Betrieb.
    • Nun stellst Du einen Bug (oder Optimierungsmöglickeit, ...) in simulation.h fest.
    • => Du musst ALLE Module neu compilieren und linken (ausgabe.cpp, simulation.cpp, kommunikation.cpp,xKram.cpp, yKram.cpp) und
    • nicht nur die X-Kunden,
    • sondern auch die Y-Kunden neu beliefern (obwohl die das simulation-Modul gar nicht nutzen).

    Einerseits sehr häßlich aufwendig und kundenunfreundlich ... andererseits ist DER Rebuild garantiert nicht mehr schneller als wenn Du nur ein Projekt builden musst.
    Um so etwas zu vermeiden, hat man Modularisierung erfunden - vor ca. 20 Jahren - und sie hat sich seitdem bewährt.
    Nach meiner Erfahrung sind sowieso Buildzeiten das schwächste Argument, das erst dann zur Geltung kommt, wenn alle anderen (fachlichen und technischen Argumente) keine Entscheidung vorgeben...

    Gruß,

    Simon2



  • CStoll schrieb:

    Und was, wenn du erst im Nachhinein feststellst, daß sich zwei gegebene Klassen doch brauchen?

    geht nicht. wenn ich es mit einer forward declaration nicht lösen kann, dann habe ich sowieso ein problem, precompiled header hin oder her. oder verstehe ich die frage falsch?

    Simon2 schrieb:

    [zeug]

    alles schön und richtig. fakt bleibt: ich habe mehrere größere projekte so auf- oder umgebaut, es gab nie probleme. im gegenteil: bei den umgebauten haben immer alle beteiligten einhellig gesagt, dass sie nachher flüssiger arbeiten konnten, weil die kompilierung insgesamt schneller ablief.

    deine argumente mögen fachlich und der theorie korrekt sein und für bestimmte projekte mag meine herangehensweise vielleicht ineffizient sein. ich hab aber noch kein solches gesehen (was nicht heißt, dass es sie nicht gibt). ich habe vor ein paar jahren noch genau das gleiche wie du erzählt. bis ich es an einem größeren projekt mal ausprobiert habe.

    Um so etwas zu vermeiden, hat man Modularisierung erfunden - vor ca. 20 Jahren - und sie hat sich seitdem bewährt.

    richtig und deshalb sind alle meine projekte auch modularisiert aufgebaut. es gibt ein modul fürs audio, eins für eingabegeräte, eine für die grafik, etc... alles schön in libraries verpackt. und jede hat einen masterheader.

    Simon2 schrieb:

    Spätestens wenn Du Deine Sourcen mehrfach verwendest (in unterschiedlichen Versionen oder Projekten), schießt Du Dir mit dieser Vorgehensweise übelst ins Knie.

    nein, denn source der projektübergreifend verwendet werden soll, ist natürlich ein eigenständiges projekt und wird in eine lib kompiliert.


Anmelden zum Antworten