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

11

29.01.2009, 21:19

Okay, dann denk ich mal, muss ich es wohl ein bisschen anders machen. Trotzdem danke!

12

29.01.2009, 21:35

Womöglich hast du irgendwo wilde Zeiger, nicht initialisierter Speicher oder Pufferüberläufe. Das passiert schnell, wenn man mit rohen Arrays anstatt Containern arbeitet (versteckter Ratschlag in diesem Satz ;))...

Falls du den Fehler nicht finden solltest: Versuch doch, dein Programm Schritt für Schritt zu abstrahieren, indem du Unwesentliches weglässt. Das machst du solange, wie der Fehler auftritt. Am Schluss sollte ein überblickbarer Code vorhanden sein, den du nach dem Fehler absuchen kannst.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

13

29.01.2009, 22:13

Zitat von »"Gotbread"«

der compiler denkt, dass er ein zeiger auf base bekommt. a hat in der
klasse den offset 0. in der abgeleiteten klasse kann es genauso sein,
aber es scheint als ob es bei dir genau anders herum ist (erst derived, dann
base).


Wenn dem so wäre dann müsste der Compiler sich drum kümmern indem er bei dem impliziten upcast von Derived* nach Base* den Zeiger verschiebt. Kann also nicht das Problem sein

abgesehen davon funktioniert der code:

http://codepad.org/aKqOzPg4

Was für einen Compiler verwendest du?

Gotbread

Alter Hase

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

14

29.01.2009, 22:48

Zitat von »"Nexus"«

Zitat von »"Gotbread"«

das kann ich dir sagen.

der compiler denkt, dass er ein zeiger auf base bekommt. a hat in der
klasse den offset 0. in der abgeleiteten klasse kann es genauso sein,
aber es scheint als ob es bei dir genau anders herum ist (erst derived, dann
base).
Das ist falsch. Wenn man Member über den Bezeichner anspricht, hat man sicher nie Probleme wegen Vererbung. Es wäre ja witzlos, wenn man in abgeleiteten Klassen zuerst implementierungsabhängige Mittel einsetzen müsste, um an Member der Basisklasse zu gelangen... :roll:


muss nicht. das bei einer abgeleiteten klasse die daten der baseclass
zuerst stehen, ist zwar einfach zu implementieren, deshalb wahrschein-
lich auch von einigen compilern genutzt, aber zwingend ist das nicht.
wenn der compiler die basezeiger um dieses offset verschiebt, für
den benutzer hinter einem implizitem cast verborgen, ist es nicht
auszuschließen, dass das ganze z.b. mit reinterpret fehlschlägt.

Zitat von »"Nexus"«


Zitat von »"Gotbread"«

wär doch ne idee für C++0x: virtuelle daten :D
Ein Einsatzbeispiel würde mich jetzt wirklich interessieren... ;)


damit man dieses problem umgehen kann. damit man auch ne vtbl für
daten hat. war nur ne idee die mir spontan kam habs nicht ausüberlegt.

Zitat von »"Nexus"«


Nicht wirklich. Die Member sind innerhalb einer einzelnen Klasse in der Reihenfolge abgespeichert, in der sie deklariert wurden (möglicherweise noch ausgerichtet).


kannst du mir das im standard zeigen? ich meine auch, dass es nicht
vorgeschrieben ist. natürlich machen 99.352% aller compiler das so,
aber gesetz ist es vermutlich (da keine beweise) nicht. und in welcher
reihenfolge steht die basisklasse?

Zitat von »"Nexus"«


Wenn dem so wäre dann müsste der Compiler sich drum kümmern indem er bei dem impliziten upcast von Derived* nach Base* den Zeiger verschiebt. Kann also nicht das Problem sein


dem schließe ich mich an, allerdings sagt das nichts über die position aus.
(ok mein erster beitrag stimmt damit nicht ganz)

allerdings ist das problem des TE ein indiz dafür, das da was nicht tut
wie es tun soll.
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

15

29.01.2009, 23:14

Zitat von »"Gotbread"«

muss nicht. das bei einer abgeleiteten klasse die daten der baseclass
zuerst stehen, ist zwar einfach zu implementieren, deshalb wahrschein-
lich auch von einigen compilern genutzt, aber zwingend ist das nicht.
wenn der compiler die basezeiger um dieses offset verschiebt, für
den benutzer hinter einem implizitem cast verborgen, ist es nicht
auszuschließen, dass das ganze z.b. mit reinterpret fehlschlägt.


ja. reinterpret_cast: wers tut is selber schuld. mehr gibts da nicht zu sagen. reinterpret_cast auf basiszeiger und dann zugreifen is undefiniert (wie so ziemlich alles wo das ergebnis von nem reinterpret_cast dereferenziert wird).

Zitat von »"Gotbread"«


damit man dieses problem umgehen kann. damit man auch ne vtbl für
daten hat. war nur ne idee die mir spontan kam habs nicht ausüberlegt.


es gibt doch gar kein problem zu umgehen. der code da oben ist korrekt. vielleicht hat sein compiler nen bug...

Zitat von »"Gotbread"«


Zitat von »"dot"«


Wenn dem so wäre dann müsste der Compiler sich drum kümmern indem er bei dem impliziten upcast von Derived* nach Base* den Zeiger verschiebt. Kann also nicht das Problem sein


dem schließe ich mich an, allerdings sagt das nichts über die position aus.
(ok mein erster beitrag stimmt damit nicht ganz)


Die Position ist auch irrelevant, der Compiler muss einfach Code erzeugen der auf den entsprechenden Basismember zugreift...

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

16

29.01.2009, 23:56

Re: Zeiger auf Basisklasse

Hi,

C-/C++-Quelltext

1
std::cout << param[0].a;


Das ist sehr komisch geschrieben. Es ist praktisch das selbe wie param->a, aber sobald du param[1].a schreibst (was du vermutlich bei dir tust), wird nur Mist gebaut;) Das würde nämlich implizit voraussetzen, dass ein Element von dem Array genausogroß ist wie base. Und das ist die abgeleitete Klasse natürlich nicht.
Als Workaround könntest du der Methode als zusätzlichen Parameter die Größe eines Arrayelementes geben.

Ciao
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

17

30.01.2009, 13:25

Zitat von »"Gotbread"«

muss nicht. das bei einer abgeleiteten klasse die daten der baseclass
zuerst stehen, ist zwar einfach zu implementieren, deshalb wahrschein-
lich auch von einigen compilern genutzt, aber zwingend ist das nicht.
wenn der compiler die basezeiger um dieses offset verschiebt, für
den benutzer hinter einem implizitem cast verborgen, ist es nicht
auszuschließen, dass das ganze z.b. mit reinterpret fehlschlägt.
Ich sagte, wenn man Member über den Bezeichner anspricht. Dass man mit reinterpret_cast die Möglichkeit hat, nahezu alle Gesetze zu umgehen, ändert nichts daran.

Zitat von »"Gotbread"«

damit man dieses problem umgehen kann. damit man auch ne vtbl für
daten hat. war nur ne idee die mir spontan kam habs nicht ausüberlegt.
Ich meinte nur, meistens wären "virtuelle Daten" auch durch virtuelle Funktionen möglich, die Daten zurückgeben. Deshalb würde mich ein Fall, wo das nicht geht, interessieren... ;)

Zitat von »"Gotbread"«

kannst du mir das im standard zeigen? ich meine auch, dass es nicht
vorgeschrieben ist. natürlich machen 99.352% aller compiler das so,
aber gesetz ist es vermutlich (da keine beweise) nicht. und in welcher
reihenfolge steht die basisklasse?
Hm, das mit der Speicherreihenfolge scheint gerade nur für die Structs aus C zu gelten. Das erklärt auch, weshalb das Makro offsetof() nur auf POD-Typen angewandt werden kann. Aus dem C++-Standard:

Zitat von »"9.2/12"«

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1)


Zitat von »"Gotbread"«

allerdings ist das problem des TE ein indiz dafür, das da was nicht tut
wie es tun soll.
Ein Indiz? Er sagt ja selber, bei sich habe es anschliessend auch funktioniert. Er hat das ursprüngliche Problem nicht richtig abstrahiert...

18

30.01.2009, 13:30

Zitat

Was für einen Compiler verwendest du?

Microsoft VC++ 2008

Zitat

aber sobald du param[1].a schreibst (was du vermutlich bei dir tust), wird nur Mist gebaut;)

Jap, genau was tue ich bei mir.

Zitat

Als Workaround könntest du der Methode als zusätzlichen Parameter die Größe eines Arrayelementes geben.

Ok, dies ist wegen der unterschiedlichen Größe einleuchtend, aber wie soll ich dann weitermachen?

19

30.01.2009, 13:35

Ich würde eher dazu raten, Container aus Zeigern zu verwenden. Also beispielsweise std::vector<Base*>. Hinter so einem Base* verbirgt sich entweder ein einzelnes Base oder ein Derived, aber kein Array. Man kann auch Boost.Pointer Container benutzen, wenn man sich nicht um die Freigabe kümmern will. Nur daran denken, den Destruktor virtuell zu machen... ;)

defaultplayer^^, wo kommst du denn nicht mehr weiter?

20

30.01.2009, 15:06

Zitat

defaultplayer^^, wo kommst du denn nicht mehr weiter?
Bei Helmuts Vorschlag, die Größe eines Elements mitzuschicken. Mir ist wie gesagt klar, was da das Problem ist, und weshalb man darum die Größe mitschicken kann, aber nicht, wie ich dann weitermach, wenn ich die Größe hab.

Dein Vorschlag, std::vector zu verwenden gefällt mir auch, wollte ich auch schonmal machen, aber ich dachte, es gäbe sicherlich noch andere ("bessere") Möglichkeiten.

Werbeanzeige