Anzeige:
Ergebnis 1 bis 6 von 6

Thema: C++-Anfänger braucht Stilempfehlung für Strings in Klassen

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47

    C++-Anfänger braucht Stilempfehlung für Strings in Klassen

    Hallo miteinander. Habe eine Frage, da mir noch der Weit- und Durchblick für C++, insbesondere für Zeiger und Refenzen im Umgang mit Objekten fehlt.

    Man stelle sich eine einfache Klasse Person vor, welche nur ein privates Feld name vom Typ std::string hat. Trivial, gel?

    Für den Namen gibt es nun den üblichen Getter und Setter. Die Klasse Person hat zudem einen Konstruktor um das Feld zu initialisieren, also Person::Person(std::string name) und einen leeren Konstruktor, der das Feld mit einem Leerstring initialisiert.

    Dabei wünsche ich mir als Klassenentwickler natürlich
    • einfache Handhabung für den Nutzer der Klasse
    • das String-Objekt sollte mit dem entsprechenden Personen-Objekt zerstört werden


    Die Frage:
    Welchen Typ nehme ich für das lokale Feld name? Einfach string oder string* oder string& ? Bei meinen bisherigen Experimenten funktionierte nur die Zeigervariante. Die native Form (kein Zeiger, keine Referenz) machte Ärger bei der Initialisierung im leeren Konstruktor. Eventuell wurde das String-Objekt nach verlassen des Konstruktor-Scopes aufgelöst und meine Objektvariable zeigte in ungenutzten Speicher ... keine Ahnung. Bei einem Zeiger ist die Verwendung für den Anwender aber hackelig. Da wären mir Referenzen lieber.

    Also: wie macht Ihr das? Ein C++-String als Objektvariable? Nativ, als Zeiger, als Referenz? Konvertieren Setter, Getter oder Konstruktoren den Typ (dereferenzieren, etc...)?

    Danke für alle Hinweise, Warnungen, Erfahrungen und mir unbekannte „best practices“!

  2. #2
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Ich würde das als normale Member-Variable machen. Worin genau bestehen denn deine Initialisierungsprobleme? Kurzcodebeispiel?

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  3. #3
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Hi und danke schon mal.
    Also:
    Ich habe meinen Anwendungsfall mittlerweile auch mit einer einfachen Membervariable realisiert. Das Initialisierungsproblem kann abgehakt werden. Das Problem war ein ganz anderes: C++ erlaubt keine verschachtelten Konstruktoraufrufe, und solche hatte ich verwendet. Nur hat mich der Fehler-Phänotyp irritiert: In Konstruktor A hatte ich beim Versuch Konstruktor B aufzurufen ein neues Objekt erzeugt, welches mit dem Ende von Konstrukor A wieder verschwand. Die Membervariable des äußeren Objektes blieb natürlich unberührt und so sah es für mich einfach danach aus, als sei das String-Objekt wieder „verschwunden“.

    Nun ja, dennoch bleibt eine Frage:

    Der Getter ist bei mir nun vom Typ string und wie ich bemerkte, legt C++ bei der Rückgabe durch den Getter eine Kopie meiner Membervariable an. Möchte man jedoch direkt das String-Objekt durch den Getter zurückgeben, bleibt mir nix anderes als den Rückgabetyp auf string* zu ändern und die Adresse meiner Membervariable zurückzugeben; Ist das richtig?

    Wie machen das C++-Entwickler gewöhnlich? Im Getter Kopien oder Zeiger zurückgeben? Oder ist das ein beliebiges Durcheinander? Gibt's da (Namens-)Konventionen?

    Und noch eine Frage:
    Wie handhabt C++ das bei anderen (eigenen) Objekttypen? Werden da auch Kopien erzeugt? Bin ich daher genötigt, immer Copy-Konstruktoren zu schreiben? Falls nicht: handelt es sich dann immer um flache Kopien?

    Danke für weitere Aufklärung!
    Ein Java-Verdorbener...

  4. #4
    Registrierter Benutzer Avatar von sommerfee
    Registriert seit
    02.07.2006
    Beiträge
    1.603
    Zitat Zitat von McFraggle Beitrag anzeigen
    Nur hat mich der Fehler-Phänotyp irritiert: In Konstruktor A hatte ich beim Versuch Konstruktor B aufzurufen ein neues Objekt erzeugt, welches mit dem Ende von Konstrukor A wieder verschwand. Die Membervariable des äußeren Objektes blieb natürlich unberührt und so sah es für mich einfach danach aus, als sei das String-Objekt wieder „verschwunden“.
    Das ist richtig so. Person(...) erzeugt eine (neue) Instanz von Person auf dem Stack, wie z.B. in "Person x = Person(...);".

    Java kann es sich hier erlauben, stattdessen den Konstruktor aufzurufen, weil es keine Instanzen auf dem Stack kennt, und daher Instanzen grundsätzlich mit "new" erzeugt werden müssen. (In C++ ist die von Java bekannte Notation aber bereits anderweitig belegt, siehe oben.)

    Der Getter ist bei mir nun vom Typ string und wie ich bemerkte, legt C++ bei der Rückgabe durch den Getter eine Kopie meiner Membervariable an. Möchte man jedoch direkt das String-Objekt durch den Getter zurückgeben, bleibt mir nix anderes als den Rückgabetyp auf string* zu ändern und die Adresse meiner Membervariable zurückzugeben; Ist das richtig?
    Ich persönlich würde "const string&" zurückgeben. Das kann man direkt verwenden, ohne daß eine Kopie angelegt wird, man kann aber auch durch Zuweisung eine Kopie anlegen, wenn gewünscht.

    Wie handhabt C++ das bei anderen (eigenen) Objekttypen?
    C++ hat im Gegensatz zu Java keine eigenen Objekttypen.

    Bin ich daher genötigt, immer Copy-Konstruktoren zu schreiben?
    Wenn der implizit erzeugte Copy-Konstruktor ein Problem erzeugen würde (z.B. ein Speicherleck), ja, dann sollte man einen eigenen schreiben. Wenn man grundsätzlich keine Kopien braucht, würde ich den sicherheitshalber trotzdem (als leere Hülle) schreiben, und zwar als "private" deklariert, damit der Compiler bei der Verwendung eine Fehlermeldung wirft. (Gleiches gilt für operator=).

    Liebe Grüße,
    Axel
    Geändert von sommerfee (04-08-2010 um 18:15 Uhr)

  5. #5
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Hi! Danke für die Infos!

    Drei kleine Fragen noch dazu:

    Ich persönlich würde "const string&" zurückgeben.
    Das heißt also, dass es hier keinen einheitlichen Stil gibt, richtig?

    Ich persönlich würde "const string&" zurückgeben. Das kann man direkt verwenden, ohne daß eine Kopie angelegt wird, man kann aber auch durch Zuweisung eine Kopie anlegen, wenn gewünscht.
    Das bedeutet, der Anwender meiner Klasse bekommt eine direkte Referenzauf meinen Member, kann diesen aber nicht verändern? Wenn ich nun auf diese Weise ein Objekt zurückgebe, welches selber wiederum manipulierende Methoden (nicht const, etwa Setter) besitzt, können diese dann vom Benutzer meiner Klasse aufgerufen werden?

    C++ hat im Gegensatz zu Java keine eigenen Objekttypen.
    Äh, mit dem Wort Objekttyp meinte ich „Klasse“. Was ist denn dann ein Objekttyp?


    Bin immer wieder begeistert von diesem Forum...

  6. #6
    Registrierter Benutzer Avatar von sommerfee
    Registriert seit
    02.07.2006
    Beiträge
    1.603
    Zitat Zitat von McFraggle Beitrag anzeigen
    Das bedeutet, der Anwender meiner Klasse bekommt eine direkte Referenzauf meinen Member, kann diesen aber nicht verändern? Wenn ich nun auf diese Weise ein Objekt zurückgebe, welches selber wiederum manipulierende Methoden (nicht const, etwa Setter) besitzt, können diese dann vom Benutzer meiner Klasse aufgerufen werden?
    Nein, es können dann nur diejenigen Methoden aufgerufen werden, die als "const" gekennzeichnet sind, ansonsten gibt es einen Compilerfehler.

    Äh, mit dem Wort Objekttyp meinte ich „Klasse“.
    So hatte ich es auch interpretiert. C++ hat keine eingebauten Funktionen und keine eingebauten Klassen. Man muß bei C++ unterscheiden zwischen der Sprache und der Standard-Laufzeitbibliothek, die z.B. std::string bereitstellt. Entwickelt man z.B. Kernel-Gerätetreiber für Windows in C++, stehen stattdessen andere (von MS bereitgestellte) Laufzeitbibliotheken zur Verfügung. Für Qt-Applikationen könnte man zwar std::string nehmen, nimmt aber in der Regel QString stattdessen, bei MFC-Anwendungen CString usw.

    Bei Java ist das ja ein wenig anders, es gibt dort auch "eingebaute" Klassen wie Object, Int, String etc.

    Liebe Grüße,
    Axel

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •