Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Cast verhindern bzw. sind diese cast ok?

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
19.08.2008, 22:56 Uhr
hilefoks



Hi,

ich habe in meinem Code zwei Typkonvertierungen und bin mir nicht sicher ob diese so okay sind.

Der erste soll Code duplizierung verhindern. Er sieht etwa so aus:

C++:
Element* Element::siblingAt(int index) const {
    return const_cast<Element*>( static_cast<const Element&>(*this).siblingAt(index) );
}

Ich empfinde es hier als okay const zu entfernen, da ja der Aufrufer vom nicht konstanten foo() ein nicht konstantes Objekt besitzen muss.


Der andere Cast ist etwas komplizierter zu erklären. Die Methode steckt sozusagen in einer doppelt verkettenten Liste (eigentlich ein Baum, spielt hier gerade aber keine Rolle) und soll das Element an einem bestimmten Index zurückgeben.


C++:
const Element* Element::siblingAt(int index) const
{
    assert( index >= 0 );
    assert( index <= countSiblings() );
  
    Element *c = const_cast<Element*>(this);
    while(c->m_prevsibling)
        c = c->m_prevsibling;

    for(int i=0; i <= index; ++i, c = c->m_nextsibling);

    return c;
}


Eigentlich, so finde ich, ist es falsch das const vom this-Zeiger zu entfernen. Daher weiss ich nicht ob es okay ist dies zu tun. Ich hab aber auch keine Idee wie ich es anders machen könnte.

Vielen Dank,
Hilefoks
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
20.08.2008, 00:00 Uhr
0xdeadbeef
Gott
(Operator)


Das Problem im ersten Codestück ist, dass du aus einer const-Methode eine Variable zurückgibst. Wenn ich das richtig sehe, willst du

C++:
Element *Element::silblingAt(int index) {
  return const_cast<Element*>(static_cast<Element const*>(this)->siblingAt(index));
}




Im zweiten Codestück, warum benutzt du nicht einfach

C++:
Element const *c = this;


...und machst dann einfach weiter? c ist dann ein Zeiger auf Element const, aber selbst nicht konstant. (Dazu bäruchte es schon Element const *const)

Die Verwendung von const_cast ist nicht schön, hier aber verzeihbar. Da es sich streng genommen um unterschiedliche Typen handelt, wäre ggf. auch die Verwendung von Funktionsvorlagen denkbar, in etwa so:

C++:
class Element {
public:
  Element *siblingAt(std::size_t index) { return sib_aux<Element*>(index); }
  Element const *siblingAt(std::size_t index) const { return sib_aux<Element const *>(index); }

private:
  template<typename T> T sib_aux(std::size_t index) {
    assert( index >= 0 );
    assert( index <= countSiblings() );
  
    T c = this;
    while(c->m_prevsibling)
        c = c->m_prevsibling;

    for(int i=0; i <= index; ++i, c = c->m_nextsibling);

    return c;
  }
};


Bei einer privaten template wie hier kann man da sogar die Implementierung in der Source-Datei verstecken.

Wirklich empfehlen würde ich aber die Benutzung eines vernünftigen Listenkopfes, oder gleich std::lists.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 20.08.2008 um 00:01 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
20.08.2008, 03:18 Uhr
hilefoks




Zitat von 0xdeadbeef:
Das Problem im ersten Codestück ist, dass du aus einer const-Methode eine Variable zurückgibst.

Warum ist das ein Problem? Oder war das Problem nur in meinem Code?


Zitat von 0xdeadbeef:
Wenn ich das richtig sehe, willst du [...]

Genau. Meine Variante kompilierte zwar, deine ist aber zweifellos die die ich implementieren wollte. Ich hatte die Existenz von "T const *" total vergessen.


Zitat von 0xdeadbeef:
Im zweiten Codestück, warum benutzt du nicht einfach

C++:
Element const *c = this;



Ja, - danke.


Zitat von 0xdeadbeef:
Da es sich streng genommen um unterschiedliche Typen handelt, wäre ggf. auch die Verwendung von Funktionsvorlagen denkbar, in etwa so: [...]

Oh - das sieht gut aus. Vielen Dank.

Erlaube mir eine persönliche Frage: Ich habe viele Beiträge in diesem Forum gelesen und daher auch viele deiner Antworten gesehen. Diese vermitteln mir das du (zumindest aus meiner Sicht) ein enormes C++ Wissen besitzt. Ich persönlich habe einige C++ Bücher gelesen und lese und programmiere seit ca. einem Jahr Qt/KDE Sourcecode. Deine "Kniffe" habe ich in diesen Quellen aber noch nicht gefunden. Mein Frage ist nun: Welche Bücher / welchen Sourcecode muss ich lesen um irgendwann (sagen wir in 5 Jahren) deine "Kniffe" genauso verinnerlicht zu habe?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
20.08.2008, 06:01 Uhr
hilefoks



Hi,

mh - deine Implementierung (das Template) funktioniert doch so nicht, oder?

Also was ich meine ist das die Zeile "T c = this;" im Template doch auch so nicht funktioniert. Es wird doch, wenn ich das jetzt alles richtig verstehe, dieser Code erzeugt "Category const * c = this;" wenn es im konstanten Kontext aufgerufen wird. Da dann aber this nicht const ist, da die Methode nicht const ist dürfte es nicht kompiliert werden.

Deklariert man die Template-Methode aber als const dürfte es ebenso wenig funktionieren, da dann "Category *c = this;" mit this = const ein Fehler ist.

Sehe ich das richtig? Sorry - es ist spät (bzw. früh). ;-)

MfG,
Hilefoks

Dieser Post wurde am 20.08.2008 um 06:02 Uhr von hilefoks editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
20.08.2008, 16:38 Uhr
0xdeadbeef
Gott
(Operator)


Hmm...ja, das ist richtig. Ich hatte das jetzt auch nicht getestet, und das Problem wohl übersehen.

Ich habe im Moment nur wenig Zeit, werde mir darüber aber nachher mal Gedanken machen.

Was die Frage davor angeht, ich hatte Leute um mich, die C++ schon gut kannten (gute Lehrmeister, könnte man sagen), außerdem habe ich seinerzeit spaßeshalber mit den hirnverrenkigeren Dingen rumgespielt (Stichwort: Template-Metaprogrammierung), und ansonsten ist es einfach Erfahrung. Manche Techniken lernt man erst zu schätzen, und manches Verständnis entwickelt sich erst, wenn man mindestens zwei mittelgroße Projekte in den Sand gesetzt hat.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
20.08.2008, 19:01 Uhr
hilefoks




Zitat von 0xdeadbeef:
Hmm...ja, das ist richtig. Ich hatte das jetzt auch nicht getestet, und das Problem wohl übersehen.

Ich habe im Moment nur wenig Zeit, werde mir darüber aber nachher mal Gedanken machen.

Kein Problem. Meine Frage hast du eigentlich ja auch schon beantwortet. Da deine Template-Methode prinzipiell aber sehr interessant und elegant ausschaut bin ich doch noch gespannt ob du zu dem Problem noch eine Lösung findest.


Zitat von 0xdeadbeef:
Was die Frage davor angeht, ich hatte Leute um mich, die C++ schon gut kannten (gute Lehrmeister, könnte man sagen), außerdem habe ich seinerzeit spaßeshalber mit den hirnverrenkigeren Dingen rumgespielt (Stichwort: Template-Metaprogrammierung), und ansonsten ist es einfach Erfahrung.

Ergibt Sinn. Leider fehlen mir solche Leute. Im Studium scheinen sich leider alle nur für Java zu interessieren - C++ Programmierer kenne ich keine. Es gibt lediglich eine Wahlpflichtveranstaltung zu C++, diese geht aber auch nicht über die Grundlagen hinaus.

Im Netz findet man zwar durchaus fähige Leute. Leider haben diese aber meist genauso viele soziale Inkompetenzen wie C++ Know-how. Ausnahmen wie du bestätigen da wohl nur die Regel. Nun gut - genug gejammert - war eigentlich gar nicht meine Absicht. ;-)


Zitat von 0xdeadbeef:
Manche Techniken lernt man erst zu schätzen, und manches Verständnis entwickelt sich erst, wenn man mindestens zwei mittelgroße Projekte in den Sand gesetzt hat.

Hehe - wohl wahr. Ging mir bisher auch mit jeder gelernten Sprache so und auch jetzt mit C++ bin ich gerade wieder dabei (und nicht zum ersten mal). Sei es drum - ich habe zwar immer eine konkrete Anwendung vor Augen - letztlich geht es mir aber nur um den Lerneffekt.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
23.08.2008, 12:45 Uhr
0xdeadbeef
Gott
(Operator)


Moin,

Ich hatte das hier schon fast wieder vergessen, tut mir leid...

Also, die Lösung für die Vorlage ist denkbar simpel:

C++:
class Element {
public:
  Element *siblingAt(std::size_t index) { return sib_aux<Element*>(this, index); }
  Element const *siblingAt(std::size_t index) const { return sib_aux<Element const *>(this, index); }

private:
  template<typename T> static T sib_aux(T c, std::size_t index) {
    assert( index >= 0 );
    assert( index <= c->countSiblings() );
  
    while(c->m_prevsibling)
        c = c->m_prevsibling;

    for(int i=0; i <= index; ++i) c = c->m_nextsibling;

    return c;
  }
};


...aber wie gesagt, ich würde hier wirklich einen echten Listenkopf benutzen. Die Art der Listenverwaltung, die du da benutzt, macht eigentlich nur dann Sinn, wenn jedes Element seine eigene Liste darstellt (das ist für bestimmte mathematische Erwägungen sinnvoll), und jede Operation deshalb vom Element selbst ausgeht, also siblingAt(1) z.B. *m_nextsibling zurückgäbe.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
25.08.2008, 16:11 Uhr
hilefoks




Zitat von 0xdeadbeef:
Ich hatte das hier schon fast wieder vergessen, tut mir leid...

Muss es nicht.


Zitat von 0xdeadbeef:
Also, die Lösung für die Vorlage ist denkbar simpel [...]

Hehe - das ist wirklich simpel. Da hätte ich auch schon selbst drauf kommen können. ;-)


Zitat von 0xdeadbeef:
...aber wie gesagt, ich würde hier wirklich einen echten Listenkopf benutzen. [...]

Jo, meine Implementierung war nicht so der Hit. Die Frage mit dem Template hat mich dann aber eher allg. interessiert.

Danke für die ausführlichen Antworten!

MfG,
Hilefoks
 
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: