Private-Member angeben



  • Private schrieb:

    Gutes Argument. Ich vermute, weil Compiler heutzutage einfach alles fressen, egal ob es C oder C++ heißt. Solange die entsprechenden Includes da sind, lässt sich alles leicht vermischen (wobei ich dir zustimme: man sollte es nicht vermischen). Ich werde zukünftig drauf achten.

    Zumindest der C++ Compiler frisst das meiste, da C++ natürlich aus C entstanden ist und eine gewisse Rückwärtskompatibilität pflegt*. So wurde auch struct einfach aus C übernommen und um ein "Paar" Dinge wie Konstruktor/Destruktor, Memberfunktionen und Sichtbarkeit erweitert. Für die Rückwärtskompatibilität soll sich ein C++ struct ohne die neuen Features dann möglichst wie in C struct verhalten, weshalb auch die Sichtbarkeit standardmäßig public sein muss.

    *Ganz kompatibel ist C mit C++ nicht. So konnte man in C noch seine Variablen "new" und "class" nennen was in C++ natürlich nicht mehr geht. Außerdem gibts noch einige kleinere Unterschiede z.B. bei inline Funktionen.


  • Mod

    Private schrieb:

    SeppJ schrieb:

    Wenn du C++ programmierst, wieso lässt du dich dann von einer komplett anderen Sprache beeinflussen, bloß weil diese auch ein "C" im Namen hat?

    Gutes Argument. Ich vermute, weil Compiler heutzutage einfach alles fressen, egal ob es C oder C++ heißt. Solange die entsprechenden Includes da sind, lässt sich alles leicht vermischen (wobei ich dir zustimme: man sollte es nicht vermischen). Ich werde zukünftig drauf achten.

    Das ist absolut nicht der Fall. Viele Compiler können mehrere Sprachen in dem Sinne, als das mehrere verschiedene Compiler in der gleichen Executable untergebracht sind (oder genauer: mehrere Compiler stecken hinter einem einheitlichen Backend). Eventuell mit Heuristiken, die beispielsweise anhand von Dateiendungen erraten, was für eine Sprache benutzt werden soll. Aber ein C++-Compiler (oder ein Multisprachcompiler im C++-Modus) wird kein C-Programm verstehen und umgekehrt ebenfalls nicht*. Am ehesten geht noch ein C-Programm mit einem C++-Compiler zu übersetzen, so lange der C-Programmierer bewusst auf Dinge verzichtet hat, die in C++ nicht gehen.



  • Danke Euch beiden, wieder etwas schlauer (und nächstes mal hoffentlich genauer).


  • Mod

    sebi707 schrieb:

    *Ganz kompatibel ist C mit C++ nicht. So konnte man in C noch seine Variablen "new" und "class" nennen was in C++ natürlich nicht mehr geht. Außerdem gibts noch einige kleinere Unterschiede z.B. bei inline Funktionen.

    Du hast den wichtigsten Unterschied vergessen: In C sind implizite Pointerkonvertierungen von und nach void* gang und gäbe, in C++ sind sie hingegen nicht erlaubt. Daher wird die Übersetzung von C-Programmen mit einem C++-Compiler bereits da dran scheitern, wenn ein Programm solch "exotische" Funktionen wie malloc oder memcpy benutzt.

    Es gibt noch viel mehr Unterschiede (siehe C++-Standard, Anhang C*), aber obiger ist wohl der, an dem es meistens scheitern wird.

    *: Ich frage mich, ob da bewusste Kalkulation hinter steckt, das ausgerechnet im Anhang C zu beschreiben 🙂



  • Denk dran, dass das pimpl-Objekt an einem Pointer hängt. Das heißt, es muss mit erzeugt und am Ende mitsamt dem Mutter-Objekt auch wieder zerstört werden.

    Verwende also gleich einen smart pointer! ( http://stackoverflow.com/questions/5576922/pimpl-shared-ptr-or-unique-ptr )

    Logisch, dass Du dann auch an Dinge wie Deep-Copy denken solltest, je nachdem, was Deine Klasse so machen soll.

    Noch etwas weitere Literatur:
    http://herbsutter.com/gotw/_100/

    Persönliche Anmerkungen:

    * ich bevorzuge struct statt class . Die pimpl-Klasse ist ja eigentlich nur das Private der Mutterklasse, und die soll natürlich ohne weiteres drauf zugreifen können. Zudem geht es hier meist um Daten, weniger um selbständige Funktionalität. private macht da keinen Sinn, daher gleich das Format nehmen, bei dem per default alles public ist.

    * ich nenne das Pimpl-Objekt gerne pimpl ... Dann erkennt man es immer sofort.

    class Niceguy {
    private:
        struct Niceguy_intern;    
        std::unique_ptr<Niceguy_intern> pimpl;
    };
    

    Ich habe es übrigens schon erlebt, dass man den Destructor der Mutterklasse ausdrücklich deklarieren und definieren muss, sonst hatte der Compiler/Linker gemeckert (weiß nicht mehr genau, irgendwas mit missing reference). War ein älterer gcc... Wenn bei Dir alles geht, braucht Dich das nicht zu jucken.
    PS: es muss sogar sein! Herb Sutter erklärt in dem Artikel (link oben) auch, warum.



  • Danke für die weiterführenden Links, waren mitunter sehr interessant (wenn natürlich teilweise auch repetitiv).

    minastaros schrieb:

    Denk dran, dass das pimpl-Objekt an einem Pointer hängt. Das heißt, es muss mit erzeugt und am Ende mitsamt dem Mutter-Objekt auch wieder zerstört werden.

    [...]

    Logisch, dass Du dann auch an Dinge wie Deep-Copy denken solltest, je nachdem, was Deine Klasse so machen soll.

    An all die Punkte habe ich gedacht, funktioniert auch einwandfrei.

    minastaros schrieb:

    Verwende also gleich einen smart pointer!

    Ist das eher eine Glaubensfrage? Ich konnte keine Argumente gegen ein stinknormales new/delete finden, außer, dass ein unique_ptr die Sache etwas vereinfacht:

    But the real question is why you want to use a smart pointer to begin with; it's very clear where the delete should occur, and there's no issue of exception safety or other to be concerned with. At most, a smart pointer will save you a line or two of code.

    [...]

    None of the usual smart pointers implement deep copy; you could implement one, of course, but it would probably still require a complete type whenever the copy occurs, which means that you'd still have to provide a user defined copy constructor and assignment operator (since they can't be inline). Given this, it's probably not worth the bother using the smart pointer.

    minastaros schrieb:

    Noch etwas weitere Literatur:
    http://herbsutter.com/gotw/_100/

    Dort steht:

    Prefer to hold the Pimpl using a unique_ptr. It’s more efficient than using a shared_ptr, and correctly expresses the intent that the Pimpl object should not be shared.

    Vielleicht habe ich sonstige Argumente auch einfach übersehen? Jedenfalls ist einfaches "Mach so, nicht so" für mich nicht ausreichend, wenn es anders auch zu funktionieren scheint ...

    @SeppJ: Auf der Seite herbsutter.com (Link von minastaros) stand die Antwort auf meine andere Frage (aus dem anderen Thread); wenn auch etwas "versteckt". Insofern hattest du recht, es steht auf einer der Seiten, die das pImpl-Idiom beschreiben (kannte die Seite nur nicht).



  • minastaros schrieb:

    PS: es muss sogar sein! Herb Sutter erklärt in dem Artikel (link oben) auch, warum.

    Ist das nicht noch mehr ein Argument für new/delete? Schließlich muss ich dann eh einen (Kopier-)Konstruktor und Destruktor anlegen, da ja sonst gar kein Speicher alloziert wird und das Programm gar nicht erst richtig läuft.



  • Über den Sinn von unique_ptr in einer Klasse kann man sich streiten. Wenn das delete im Destruktor steht wird der Speicher auch garantiert wieder freigegeben. Allerdings sind schon zwei Pointer in einer Klasse die mit new reserviert werden nicht mehr trivial. Bei lokalen Variablen sollte man new/delete auf jeden Fall vermeiden und unique_ptr vorziehen, da es viel zu viele Möglichkeiten gibt das delete zu vergessen.



  • Private schrieb:

    minastaros schrieb:

    PS: es muss sogar sein! Herb Sutter erklärt in dem Artikel (link oben) auch, warum.

    Ist das nicht noch mehr ein Argument für new/delete? Schließlich muss ich dann eh einen (Kopier-)Konstruktor und Destruktor anlegen, da ja sonst gar kein Speicher alloziert wird und das Programm gar nicht erst richtig läuft.

    Nicht wirklich ein Argument dafür.

    Wenn Smart Pointer grundsätzlich für verwaltete Resourcen verwendet werden, ergibt das eine gewisse Konsistenz und Wiedererkennbarkeit, was ihre Aufgabe betrifft. Damit unterscheiden sie sich auch optisch sofort von den "normalen" Pointern, bei denen es dann offensichtlich nicht um Resourcenverwaltung geht.

    Mag man so oder so sehen. Eher eine Stil-Frage, wobei sich die "Gurus" allesamt dafür aussprechen. Bei konsequenter Anwendung von Smart-Pointern wird das Leben einfach insgesamt sicherer und entspannter.


Anmelden zum Antworten