Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » operator= in abgeleiteten Klassen...

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
04.06.2004, 14:36 Uhr
KaraHead



Hi leutz,
ich hab mal ne Frage:


C++:
class X
{
  public:
    int a;
    X(int xa=0):a(xa){}
    X& operator=(const X& xop2)
    {
    a=xop2.a;
     return(*this);
    }
};

class Y:public X
{
  public:
    int b;
    Y(int ya=0,int yb=0):X(ya),b(yb){}
    Y&operator=(Y& yop2)
    {
    X::opoerator=(yop2); //explizieter Aufruf des X-zuweiungsoperator
    b=yop2.b;
    return(*this);
    };
};



Warum muss die abgeleitete Klasse Y bei ihrem eigenen "operator=" expliziet die X-operator version aufrufen?
Ich weiss wenn man einfach nur


C++:
Y&operator=(Y& yop2)
    {
    a=yop2.a;
    b=yop2.b;
    return(*this);
    };



schreibt, dann entwickelt sich eine unendliche Rekursive Schleife, falls Y auch ein element" int a" enthält und dann das abgeleitete a-element "überdeckt".
Doch man kann das doch auch so lösen, nicht oder?


C++:
Y&operator=(Y& yop2)
    {
    X::a=yop2.X::a;
    //a=yop2.a; kommt dazu, falls Y auch ein int a element enthält
    b=yop2.b;
    return(*this);
    };



Ist das möglich?

Danke schonmal. Die Frage wurde doch ein bischen umfangreicher als ich gedacht hatte

Dieser Post wurde am 04.06.2004 um 14:38 Uhr von KaraHead editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
04.06.2004, 18:59 Uhr
typecast
aka loddab
(Operator)


Wo soll da bitte eine unendliche Rekursion stattfinden? Ich seh da keine Möglichkeit wo was rekursiv werden kann.

Woher hat yop2 denn das Member X?
Und yop2.X::a kannst du afaik gar nicht schreiben...

Was das verdecken von Membern angeht, solltest du das auf jeden Fall vermeiden.
So was macht man nicht :-)
--
All parts should go together without forcing. ... By all means, do not use a hammer. (IBM maintenance manual, 1925)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
07.06.2004, 09:02 Uhr
KaraHead



Ist nicht die Ausgeburt meines Hirnes, sondern ein BSP aus nem Buch.

ABer da:
yop2.X::a
nicht geht hat sich meine Frage schon erledigt.

Thx
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
07.06.2004, 09:30 Uhr
virtual
Sexiest Bit alive
(Operator)


Hi,

solche Konstruktionen sollte man vermeiden, wie in Deinem Buch als Beispiel bneschrieben. Was ich meine ist folgendes:

C++:
class Basis
{
public:
      Basis& operator = (const Basis& src)
      {
         ...
      }
};

class Abgeleitet
{
public:
      Abgeleitet& operator = (const Abgeleitet& src)
      {
         Basis::operator=(src);
         ... // HIER
      }
};


Das Problem ist, daß solcher Code im Zweifel nicht exceptionsicher ist. Wenn an der Stelle mit dem Kommentar "HIER" aus irgendeinem Grund eine Exception geworfen wird, so hat das Objekt links von der Zuweisung im Zweifel einen Inkonsistent zustand.

Um Zuweisungoperatoren exceptionsicher zu gestalten bedient man sich in der Regel folgenden Verfahrens:

C++:
class Klasse
{
protected:
       void swap(Klasse& other)
       {
          // TODO: Vertausche die Attribute von other mit this
       }

public:
       Klasse(const Klasse& src)
       {
          // TODO: Copyctor
       }

       Klasse& operator = (const Klasse& src)
       {
            Klasse tmp(src);
            swap(tmp);
            return *this;
       }
};


Dh man braucht einen Copyctor und eben diese Swap methode. Den op= kann man dann immer auf gleiche Weise implementieren. Der so programmierte Code ist sauber + exceptionsicher.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
07.06.2004, 10:03 Uhr
KaraHead



@virtual:
aha werd zwar noch ein bischen an deiner lösung denken müssen, aber schonmal danke.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
07.06.2004, 12:07 Uhr
stephanw
localhorst


@virtual: so ganz schnalle ich den Sinn von swap im Zus.hg. mit dem Exception-Problem nicht. Die Funktionalität von op= wird damit erstmal nur in swap () ausgelagert und die Quelle ist tmp. Angenommen, beim Kopieren des 5. Attribut von src (== tmp == other) tritt eine Exception auf, dann ist this inkonsistent. Dasselbe Problem wie im oberen Fall. Der einzige der konsistent ist, ist tmp. Bei dem ist es aber egal.

Sehe ich den Wald nicht ?
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
07.06.2004, 12:50 Uhr
virtual
Sexiest Bit alive
(Operator)


@stepanw
Also "exceptionsicher" bedeutet ja nicht, daß niemals eine Exception auftreten darf, sondern daß alle involvierten Objekte im Falle einer Exception noch konsistent bleiben.
Ich mach es mal anhand folgenden Beispiel deutlich:
Erstmal die naive Methode (nicht exception sicher):

C++:
class String
{
private:
     char* ptr;
public:
     String(const char* ptr_) { ptr = new char[strlen(ptr_)+1]; strcpy(ptr, ptr_); }
     ~String() { delete[] ptr; }
     String& operator = (const String& src)
     {
          delete[] ptr;
          ptr = new char[strlen(src.ptr)+1]; // HIER
          strcpy(ptr, src.ptr);
          return *this;
     }
};


Das Problem ist die mit HIER gekennzeichnete Zeile: hier könnte ein std::bad_alloc geworfen werden, in der Folge wäre this in einem nicht konsitenten Zustand, weil ptr bereits freigegeben wurde, also ein dangling Pointer ist, der im dtor zu Problemen führen würde.
Das Problem könnte man hier natürlich umgehen:

C++:
     String& operator = (const String& src)
     {
          char* tmp = new char[strlen(src.ptr)+1]; // Eception kann geworfen werden, aber this ist noch konsistent
          delete[] ptr;
          ptr = tmp;
          strcpy(ptr, src.ptr);
          return *this;
     }


Also einen Umweg über eine lokale Variable gehen. Im Prinzip macht dieser swap Ansatz ja nichts anderes, nur eben auf eine mehr oder wenig generische Art:

C++:
class String
{
private:
     char* ptr;
public:
     void swap(String& other) { std::swap(ptr, other.ptr); }
     String(const char* ptr_) { ptr = new char[strlen(ptr_)+1]; strcpy(ptr, ptr_); }
     String(const String& src) { ptr = new char[strlen(src.ptr)+1]; strcpy(ptr, src.ptr; }
     ~String() { delete[] ptr; }
     String& operator = (const String& src)
     {
          String tmp(src); // HIER
          swap(tmp);
          return *this;
     }
};


Die einzige Stelle, wo hier jetzt eine Exception auftreten könnte, wäre die mit HIER markierte Stelle (copyctor könnte eine werfen). Das ist aber völlig unkritisch, weil weder this noch src dadurch verändert würden.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
07.06.2004, 14:06 Uhr
stephanw
localhorst


Ok, alles klar. Durch das Vertauschen der Pointer geht das natürlich. Würde man in swap() das gleiche machen wie im op= des obersten Code-Abschnitts, hätte man nichts gewonnen. Aber so ist es wirklich gut.


--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: