Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

15.11.2013, 14:19

Zuweisung Verständnisproblem

Hallo,
ich bin heute über etwas gestolpert, von dem ich felsenfest überzeugt war, das es funktioniert.
Es geht hier um folgendes Konstrukt, die Erklärung folgt danach.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

class foo
{
public:
    foo() : x(0)
    {}

    virtual ~foo() {}

private:
    int x;
};

class bar : public foo
{
public:
    bar(int param) : y(param), foo()
    {}

    int getY() { return y; }

private:
    int y;
};

int main()
{
    foo *pFirst(new bar(5));
    foo *pSec(new bar(1));

    *pSec = *pFirst;
    std::cout << dynamic_cast<bar*>(pSec)->getY() << std::endl; // gibt 1 aus obwohl ich 5 erwartet hätte
    system("pause");
}


Wie man sieht, erbt bar von foo. Ich erstelle mir also 2 bar Objecte, die ich in foo Pointer packe und versuche über eine Dereferenzierung pSec auf den Wert von pFirst zu setzen. Wie man aber ganz gut sieht, funktioniert das nicht. Und genau HIER würde mich interessieren, wieso...
Wie gesagt, bisher war ich der Meinung, das sowas funktionieren müsste, wurde aber eines besseren belehrt.

mfg

PS: Ich weiß das es ein MemoryLeak gibt ;)

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

15.11.2013, 14:23

Ich würde erwarten, dass er nur die foo-Inhalte kopiert hat, weil er gar nicht weiß, dass sich dahinter eigentlich bar Objekte befinden.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

15.11.2013, 14:28

Genau so ist es: http://en.wikipedia.org/wiki/Object_slicing ;)

Daher gehören copy ctor und copy assignment operator von polymorphen Typen in der Regel zumindest protected gemacht. Es macht evtl. Sinn, ein bar zu kopieren, aber es macht in der Regel schon kaum Sinn, ein foo zu kopieren und noch viel weniger, das foo Subobjekt eines bar in das foo Subobjekt eines anderen bar zu kopieren...

4

15.11.2013, 14:44

Ok, danke Dot.
Was wäre denn die Lösung damit obiges Beispiel funktioniert? Alle copy assignment operatoren der Subklassen selbst schreiben?

EDIT: Das würde ja auch nicht funktionieren. Wie löst man also diese Dilemma?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »anti-freak« (15.11.2013, 14:58)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

15.11.2013, 15:02

Die Frage ist erstmal: Was genau soll der Sinn von diesem Beispiel sein?

6

15.11.2013, 15:10

Der Sinn dahinter ist, das ich eine Klasse habe, die einen Container besitzt, in welchem Pointer einer Superklasse gespeichert werden. Hier landen allerdings keine Objecte der Superklasse, sondern abgeleitete drin. Dadurch erhalten andere Klassen, die diese Container Klasse nutzen natürlich nicht den wahren Typ, sondern nur die Superklasse. Die reicht normalerweise auch, nur benötige ich jetzt eben eine Zuweisung, die so eben nicht funktioniert..

Ich habe jetzt aber denke ich meine Methode gefunden, mit der ich glücklich werden kann.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class A {
public:
  virtual A& operator= (const A& a) {
    assign(a);
    return *this;
  }

protected:
  void assign(const A& a) {
    // copy members of A from a to this
  }
};

class B : public A {
public:
  virtual B& operator= (const A& a) {
    if (const B* b = dynamic_cast<const B*>(&a))
      assign(*b);
    else
      throw bad_assignment();
    return *this;
  }

protected:
  void assign(const B& b) {
    A::assign(b); // Let A's assign() copy members of A from b to this
    // copy members of B from b to this
  }
}

http://stackoverflow.com/questions/27462…ng-problem-in-c

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »anti-freak« (15.11.2013, 15:28)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

16.11.2013, 09:11

Nur funktioniert die dank fehlender RTTI in der Praxis nur recht selten. Mal davon abgesehen, dass das auch recht hässlich ist. Zumindest Zeile 17.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

16.11.2013, 09:48

Der Sinn dahinter ist, das ich eine Klasse habe, die einen Container besitzt, in welchem Pointer einer Superklasse gespeichert werden. Hier landen allerdings keine Objecte der Superklasse, sondern abgeleitete drin. Dadurch erhalten andere Klassen, die diese Container Klasse nutzen natürlich nicht den wahren Typ, sondern nur die Superklasse. Die reicht normalerweise auch, nur benötige ich jetzt eben eine Zuweisung, die so eben nicht funktioniert..

dynamic_cast ist praktisch immer Anzeichen dafür, dass mit dem Design was schiefgelaufen ist. In deinem konkreten Fall zeigt der dynamic_cast wohl, dass diese Dinge eben nicht in einen gemeinsamen Container gehören oder dass deine Superklasse unvollständig ist...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

16.11.2013, 10:04

Wahlweise auch nur, dass er echte Polymorphie nutzen sollte inklusive der notwendigen Pointer/Referenzen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

10

16.11.2013, 18:22

Das dynamic_cast ein Zeichen für schlechtes Design ist, weiß ich. Allerdings fällt mir keine gute Möglichkeit ein, meine Anforderungen anders umzusetzen.

Im Prinzip ist das Problem noch ein wenig weitläufiger als ich es hier beschrieben habe.
Könnt ihr mir vll aufzeigen unter welchen Umständen oben genannte Lösung Probleme machen könnte?
Ich sehe dabei lediglich Problem beim Ändern der Klasse (hinzufügen von Membern).

Hässlich finde ich das eigentlich eher nicht, für meine Zwecke reicht es vollkommen, außer natürlich ich übersehe etwas grundlegendes ;)

Werbeanzeige