Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » const Überladung von Member-Funktionen

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
03.07.2006, 11:10 Uhr
stephanw
localhorst


Hallo,

ich möchte zwei gleichnamige Funktionen anbieten, eine für read-only, die andere für read/write access, etwa wie folgt:


C++:
class Foo
{
public:
  int* get() {
    return _data;
  }

  const int* get() const {
    return _data;
  }

private:
  int* _data;
};



Nach meinem Verständnis wird die const-Variante für const-Objekte gerufen, die andere für nicht-const-Objekte. Ist dies wirklich so ? Gibt es eine andere Variante, explizit eine der beiden Überladungen auszuwählen ?

Das habe ich bisher vorwiegend bei trivialen Operator-Funktionen gemacht. Jetzt möchte ich in einem anderen Fall noch Argumente prüfen und ggf. eine Exception werfen. Der Code ist in beiden Fällen identisch, darum möchte ich von der einen Funktion aus lieber die andere rufen, um ncht den Code zu kopieren. Ich dachte an folgendes:


C++:
class Bar
{
  bool _running;
  int* _data;
public:
  class NotRunningException;
  
  const int* get() const throw (NotRunningException)
  {
    if ( ! _running ) throw NotRunningException();
    return _data;
  }
  int* get() throw (NotRunningException)
  {
    const Bar* This = this;
    return This->get();  // const - Variante rufen ?!
  }
};



Ist es garantiert, dass da die const-Variante gerufen wird oder kann eine Rekursion entstehen ? Geht es besser ?
--
Reden ist Schweigen und Silber ist Gold.

Dieser Post wurde am 03.07.2006 um 11:18 Uhr von stephanw editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
03.07.2006, 11:13 Uhr
Pler
Einer von Vielen
(Operator)


Ohne das ganze jetzt ganz genau gelesen zu haben:
Du kannst Funktionen nicht überladen, wenn sie sich nur duch den Rückgabetyp unterscheiden.
Das geht auch nicht mit int und double oder so.

Du brauchst also zwei verschiedene Funktionsnamen, oder einen Parameter als Flag, um auszudrücken welche Funktion genutzt werden soll.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
03.07.2006, 11:18 Uhr
stephanw
localhorst


@Pler:
die Funktion unterscheidet sich im Rückgabe-Typ UND im Const-Qualifizierer. Das geht.
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
03.07.2006, 11:20 Uhr
Pler
Einer von Vielen
(Operator)


Hm. Ist mir völlig neu
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
03.07.2006, 12:41 Uhr
Th



Ich würde eher dann von beiden Operatoren aus eine eigenständige Funktion aufrufen.

Aber das eigentliche Problem scheint die Datenkapselung zu sein.
Wenn du wirklich eine Funktion zum Ändern der Daten brauchst, dann würde ich die Funktion auch so explizit definieren, anstatt den nicht-const operator dafür zu verwenden.
In C++ wäre es auch besser, wenn du eine Referenz als Rückgabetyp definierst, anstatt diese Pointer-Gewurschtel...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
03.07.2006, 14:36 Uhr
stephanw
localhorst



Zitat:
Ich würde eher dann von beiden Operatoren aus eine eigenständige Funktion aufrufen.

Ja, klar kann ich eine eigenständige Funktion rufen. Ich wollte aber auch gleich meine Wissenslücke bezüglich der Auswahl der Funktion füllen ;-)

Zitat:
Aber das eigentliche Problem scheint die Datenkapselung zu sein.
Wenn du wirklich eine Funktion zum Ändern der Daten brauchst, dann würde ich die Funktion auch so explizit definieren, anstatt den nicht-const operator dafür zu verwenden.

Kontextabhängig. Für einen Vec3D finde ich es angenehm, wenn ich schreiben kann:

C++:
float x = vec.x();
vec.x() = 17.4;
// wobei auch vec.x( 17.4 ); gehen würde.



Zitat:
In C++ wäre es auch besser, wenn du eine Referenz als Rückgabetyp definierst, anstatt diese Pointer-Gewurschtel...
Habe ich auch. Ging nur ums Prinzip.
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
03.07.2006, 14:49 Uhr
ao

(Operator)


Hi Stephan,

normalerweise macht man für sowas eine Lese- und eine Schreibroutine, aber keine Lese-Schreib-Routine, weil man nicht im gleichen Zugriff lesen *und* schreiben will.


Zitat:


C++:
  int* get() throw (NotRunningException)
  {
    const Bar* This = this;
    return This->get();  // XXX
  }


Ist es garantiert, dass da die const-Variante gerufen wird oder kann eine Rekursion entstehen ? Geht es besser ?


Ich habs nicht ausprobiert, aber ich vermute, dass du in der Zeile XXX einen Compilerfehler kriegst, weil du versuchst, einen const int * (aus This->get ()) als nicht-const nach draußen zu reichen. Du müsstest zumindest zwischen return und This den const-Qualifier wegcasten, und das wird dann richtig dreckiger Code.

Dass hier ein Member-Pointer zum Schreibzugriff nach draußen gereicht wird, finde ich verdächtig. Damit vertraust du dem äußeren Code sozusagen deine Innereien an, und zwar nicht nur guckenderweise, sondern der darf da was dran ändern. Das ist für C++ zumindest ungewöhnlich.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
03.07.2006, 15:38 Uhr
stephanw
localhorst


@ao, ja Du hast Recht. Compilerfehler. Const_cast kommt nicht in Frage.

Wie gesagt, ich finde das nicht so pauschal schlecht, siehe den Vector von oben. Generell wollte ich dabei mal wissen, wie genau die Auswahl der Funktion ist (name-mangling), die sich im const-Qualifizierer unterscheiden.

Eine wirkliche Alternative ist schlecht, da ich die Referenz auf eine externe Resource (structs mit ca. 70 Variablen) freigebe. Ich will keine Wrapper für 70 Variablen machen. Die Resource kann ich nicht ändern. Ein komplett anderes Design will ich derzeit nicht machen. Evtl. mache ich den Kram private und gebe eine Friend-Deklaration für die eine Client-Klasse an.
--
Reden ist Schweigen und Silber ist Gold.

Dieser Post wurde am 03.07.2006 um 15:39 Uhr von stephanw editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
03.07.2006, 16:07 Uhr
ao

(Operator)



Zitat von stephanw:
Wie gesagt, ich finde das nicht so pauschal schlecht, siehe den Vector von oben.

... wobei es ein Unterschied ist, ob der Client nur ein Zahlenfeld in die Finger bekommt (vec.x) oder einen Pointer mit allem, was da dranhängen kann. Der Client muss ja mit dem Pointer richtig umgehen.

Zitat:
Generell wollte ich dabei mal wissen, wie genau die Auswahl der Funktion ist (name-mangling), die sich im const-Qualifizierer unterscheiden.

Das scheint der übliche Weg zu sein, sowas zu machen, vgl. hier: www.google.com/search?q=c%2B%2B+overload+const+accessor
Da kommen etliche Treffer zu dem Thema.

Zitat:
Eine wirkliche Alternative ist schlecht, da ich die Referenz auf eine externe Resource (structs mit ca. 70 Variablen) freigebe. Ich will keine Wrapper für 70 Variablen machen.

Sei doch nicht so faul!

Zitat:
... und gebe eine Friend-Deklaration für die eine Client-Klasse an.

Wenns nur eine Client-Klasse ist, die damit umgehen soll, dann auf jeden Fall. Dann ist das ja eigentlich gar kein Teil der öffentlichen Schnittstelle.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
03.07.2006, 16:24 Uhr
stephanw
localhorst




Danke @th und @ao !
--
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: