extern einer Klasse



  • Hallo,
    ich denke Pimpl hilft mir da nicht viel, wenn das Interface steht kann ich in der cpp auch so rumbasteln und muss nur diese Übersetzungseinheit kompilieren, ohne dass der Rest betroffen ist.
    Wird wohl nur über forward decl gehen, hmmm



  • Seikilos schrieb:

    Hallo,
    ich denke Pimpl hilft mir da nicht viel, wenn das Interface steht kann ich in der cpp auch so rumbasteln und muss nur diese Übersetzungseinheit kompilieren, ohne dass der Rest betroffen ist.
    Wird wohl nur über forward decl gehen, hmmm

    Sicher hilft dir Pimpl da weiter! Füge eine neue Membervariable im Header hinzu -> alle Nutzer müssen neukompilieren, obwohl sich am public-Interface nichts ändert.
    Füge eine neue private Helper-Funktion hinzu -> alle Nutzer müssen neukompilieren, obwohl sich am public-Interface nichts ändert.



  • Seikilos, ich habe Dein Problem nicht verstanden. Kannst Du das noch mal umschreiben, was Du erreichen willst?

    extern macht bei nicht-statischen Elementen absolut keinen Sinn.



  • Änderst du was am Interface (oder an der restlichen Definition) müssen alle die dieses benutzen neu kompilieren, da hilft goar nix.
    Die Implemntierung der Methoden interessiert -sofern sie in der cpp steht- keine Sau. Die Daten die in der Definiton stehen bestimmen die Größe des Objekts, daher müssen bei Änderungen auch alle Benutzer neu kompilieren.
    Um die öffentlichen Änderungen zu minimieren bietet sich Pimpl an. Etwas ähnliches kann man mit einer abstrakten Interfaceklasse machen. Pimpl bietet da aber die schöneren Möglichkeiten.



  • Danke an alle, werde mich morgen mal damit beschäftigen 🙂

    Sebastian Pizer schrieb:

    Seikilos, ich habe Dein Problem nicht verstanden. Kannst Du das noch mal umschreiben, was Du erreichen willst?

    extern macht bei nicht-statischen Elementen absolut keinen Sinn.

    Naja mein Problem ist, dass MyClass äußerst lange kompiliert, ich aber primär im Struct Foo arbeite und verhindern will, dass änderungen an Foo sich im Neukompilieren niederschlagen



  • Änderst du denn dauernd das Interface?

    Es wurde ja schon mehrfach erwähnt, dass dir das Pimpl-Idiom weiterhilft. Hast du dich schon genauer darüber erkundigt?



  • Noch ein paar Sachen:

    1. Wir reden davon (auf dein Beispiel bezogen) Foo zu Pimpln, nocht MyClass
    2. kannst du in jedem Fall die Implementierung von MyClass aufsplitten in einen Teil der von Foo abhängt, und in einen von Foo unabhängigen. So muss nicht ein fettes MyClass.cpp neu kompiliert werden, sondern nur der Tel, der wirklich Foo verwendet.
    3. Von wie langen Kompilierungszeiten reden wir hier?
      Ich habe ein Projekt, in dem ich mittels Swig Python-Bindings aus 15 recht umfangreichen Klassen generieren lasse. Daraus resultiert ein ~15000 Zeilen .cpp und ein .h mit ~600 Zeilen. Auf meinem 7 Jahre alten Rechner kompiliert das in ❤ Sekunden (incl. swig-Parse), also im verschmerzbaren Bereich. Ich kompilier ja nicht alle 5 Sekunden, weil ich in einem String grad rumbastel 😃

    Und da kommen wir zu
    4) Um Gottes Willen, splitte deine klasse 😃
    Wenn die echt so fett ist, dass die so lange braucht schaut das nach nem Designfehler aus 😉



  • Bin dran 🙂

    Die Klasse dauert auf diesem Rechner 3-4 Minuten zu kompilieren und das wegen Boost, diese Klasse hat halt noch n privates Struct (Foo), was ich ja gerade rausfaktorisiere, um schneller zu kompilieren.
    Auf dem Core2Duo 6600 (ist schon in die Jahre gekommen) dauert das ewig.
    Es liegt an Boost::Spirit (um genau zu sein qi, die anderen Header wir karma werden nicht benötigt und nicht included).
    Bedingt durch Spirit hab ich sehr viele Templates in dieser Klasse.

    Es wird empfohlen, nur eine include Datei für qi, die aber ne Gruppe von Includes hat. Als nächstes werde ich gucken, ob ich die nicht manuell include und nicht benötigte Header rauslasse.

    Ist auch sehr unbequem damit zu arbeiten.

    Edit:
    Was mich eigentlich interessiert. Pimpl erzeugt ja immer mindestens eine Indirektion der Methodenaufrufe auf den versteckten Teil.
    Wenn es eine Klasse ist, die massiv in performancekritischen Bereichen eingesetzt wird, ist die einfache oder doppelte Indirektion da signifikant? Es wird bei den meisten Compilern auf eine Extraanweisung hinauslaufen, oder?



  • Hm, Pimpl scheint hier ein wenig umständlich. Foo erbt bei mir von nem Objekt.
    Also ungefähr so:

    #include "big_header.h"
    struct MyClass
    {
      struct Foo : big_header::zeug
      {
         Foo(typ a);
         int zahl;
      };
    
      MyClass(typ  a);
    
      virtual inline getFoo() { return foo;}
      protected:
        Foo foo;
    
    };
    

    Wenn ich Foo pimpln würde, würd ich doch die privaten Innereien in FooImpl packen, das ist mir klar.
    MyClass hat dann ne forward decl von Foo als Pointer.
    Der MyClass Constructor in der cpp datei muss aber Foo nun initialisieren, sprich new Foo(a) übergeben. Da aber das Foo struct von big_header::zeug erbt, muss in MyClass.cpp der include her, oder? Dann ist das wieder Grütze.

    Oder läuft es so, dass Foo von nichts erbt, aber die FooImpl erbt?
    Dann muss ich den getter von Foo soweit abändern, dass er mir FooImpl, zurück gibt, nicht wahr?



  • Ob diese zusätzliche Indirektion Performanceprobleme auslöst, hängt ganz davon ab, wie komplex die übrigen Berechnungen sind.

    Zu den anderen Sachen:
    Wenn du von big_header::zeug erbst, und sich eben in big_header::zeug nichts ändert, bist du immer noch mit Foo pimpln gut bedient!
    Sollte sich big_header::zeug ändern hast du aber wieder das gleiche Problem.
    Selbiges gilt natürlich auch, wenn du jetzt nicht Foo sondern FooImpl von big_header::zeug erben lässt. Denn um jetzt FooImpl "bedienen" zu können müssen Details bekannt sein - Header includen unerlässlich! Und du hast wieder die selben Probleme.

    Aber das ist jetzt DEINE Entscheidung! Entweder Indirektion in Kauf nehmen und leichte Performance-Einbußen hinnehmen, oder bei jeder Änderng in Foo.h 3-4 Minuten Kompilieren ertragen.

    Du kannst jetzt versuchen mit Macros zu steuern, ob Pimpl oder nicht. So dass du während des Testens/Erweiterns/... ein #define setzt und Pimplst, für Produktiveinsatz (sprich Release) aber nicht. Ist sicher möglich aber kompliziert und kann wieder Fehler produzieren - und das ganze wird schwerer wartebar...



  • wenn du ur mit dem Foo rumhantierst und nicht den qi-templatekram jedesmal neu compilieren willst, kannst du auch die .cpp von MyClass in zwei ÜEs aufteilen, vorausgesetzt du hast nicht überall Foo UND qi Kram vermischt.


Anmelden zum Antworten