Forum: PC-Programmierung versteh das mit const nicht


von hausmeister krause (Gast)


Lesenswert?

es geht um c++

wann muss ich da const verwenden gibts da regeln? ich hab in einem

anderen theard ja schon mal beschrieben das der const einfach weggecatet
wurde! also wann mus ich das verwenden?

von Sachich N. (dude) Benutzerseite


Lesenswert?

Erstmal solltest du was an deiner Sprache machen, sonst wirst du hier im 
Forum auch ganz schnell "weggecatet".

von TL431 (Gast)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

hausmeister krause schrieb:
> es geht um c++
>
> wann muss ich da const verwenden gibts da regeln? ich hab in einem
>
> anderen theard ja schon mal beschrieben das der const einfach weggecatet
> wurde! also wann mus ich das verwenden?

Ist doch einfach.
Verändert sich etwas nicht, ist es also in einem gewissen Zusammenhang 
als konstant anzusehen, dann machst du es const.
Wenn Werte an Funktionen per Value übergeben werden, kannst du dir das 
const sparen, da die Funktion ja sowieso ihre eigene Kopie erhält, die 
sie nach Herzenslust verändern darf.
Aber abgesehen davon ist const ganz einfach die Zusicherung an den 
Aufrufer einer Funktion: Das was du mir gibst werde ich nicht verändern.

Bsp.

int foo( const char* string );

Die Funktion foo übernimmt einen Pointer auf eine Zeichenfolge. Und sie 
gibt die Zusicherung, dass sie die Zeichenfolge nicht verändern wird. In 
so eine Funktion kann man also bedenkenlos ein Stringliteral hineingeben

int main()
{
  foo( "Hallo world" );
}

weil foo die Zusicherung macht, sich nicht am String selbst zu 
vergreifen und ihn zu ändern (was bei Stringliteralen fatal wäre).

von hausmeister krause (Gast)


Lesenswert?

Wenn ich zb. das hier habe

const *zeichenkette = "ichbinvolltoll";

wie muss ich jetzt das an ne Funktion Übergenen?

von hausmeister krause (Gast)


Lesenswert?

const char *zeichenkette = "ichbinvolltoll";



String(const char * = "");

muss ich dann da dieses CONST vor char angeben

von hausmeister krause (Gast)


Lesenswert?

bei meinem Programm geht das auch ohne const

const char *zeichenkette = "ichbinvolltoll";



String(char * = "");

von Mikke M. (hausmeister)


Lesenswert?

@ Karl heinz Buchegger
hab dir mal den kompletten Code per pn geschickt

von Karl H. (kbuchegg)


Lesenswert?

hausmeister krause schrieb:
> Wenn ich zb. das hier habe
>
> const *zeichenkette = "ichbinvolltoll";
>
> wie muss ich jetzt das an ne Funktion Übergenen?
1
int main()
2
{
3
   foo( zeichenkette );
4
}

wahnsinnig schwer, gell :-)

Der Aufrufer braucht überhaupt nichts tun. Der übergibt seine Argumente, 
so wie bisher auch, an die Funktion.
const ist die Zusicherung der Funktion an den Aufrufer: das was du mir 
gibst - ich werde es nicht verändern. Wenn das übergebene beim Aufrufer 
selbst const ist, dann ist diese Zusicherung wichtig. Wenn es das nicht 
ist, dann ist die Zusicherung egal.

von Karl H. (kbuchegg)


Lesenswert?

hausmeister krause schrieb:
> const char *zeichenkette = "ichbinvolltoll";
>
>
>
> String(const char * = "");
>
> muss ich dann da dieses CONST vor char angeben

Die erste Frage ist immer:
Was macht die Funktion mit dem Übergebenen?
Ändert sie das Übergebene oder tut sie das nicht?

Wenn sie das Übergabeargument versucht zu verändern, dann kann das 
Übergabeargument nicht const sein (sollte eigentlich logisch sein).

Ein String Literal ist immer const!

Daher kann diese von dir skizzierte Funktion den übergebenen String 
schon nicht modifizieren. Ergo macht man das Argument const.

Stell es dir so vor:
Dein Freund gibt dir ein Buch. Du sicherst ihm zu: Ich werde nichts in 
das Buch hineinschreiben (Das Buch ist für dich const). Wenn er dir eine 
Handschrift aus dem 14. Jahrhundert gibt, dann ist diese Zusicherung für 
ihn wichtig. Wenn er dir aber einen Schmierblock gibt, dann wird es ihn 
kaum jucken, wenn du ihm zusicherst, nichts hineinzuschreiben. Du 
könntest, wenn du wolltest, aber da du ohnehin nicht willst ....

von Karl H. (kbuchegg)


Lesenswert?

hausmeister krause schrieb:
> bei meinem Programm geht das auch ohne const
>
> const char *zeichenkette = "ichbinvolltoll";
>
>
>
> String(char * = "");

Ja, das ist leider ein Zugeständnis an die Entwicklungsgeschichte von C 
und C++. Das heist trotzdem nicht, dass es korrekt ist.
Richtig ist:
ein String Literal ist immer const.
Einen const Pointer kann man nicht an einen nicht const Pointer 
zuweisen.

Soweit zur Theorie. Für const char* und char * wird explizit eine 
Ausnahme gemacht, weil sonst Unmengen an altem Code (vor allem Code der 
von C nach C++ übernommen wurde) nicht mehr compilierbare wäre. Das 
bedeutet aber nicht, dass es korrekt ist. Es ist mehr eine Ausnahme: 
"Wir erlauben das ausnahmsweise, aber die Benutzung ist auf eigene 
Gefahr"

Für neueren Code gibt es keinen Grund diese Praxis weiterzuführen. const 
korrekt programmieren kostet nichts und beugt potentiellen Fehlern vor. 
Ganz abgesehen davon, kann es dem Compiler helfen Optimierungen 
anzubringen, die sonst nicht möglich wären.

von Karl H. (kbuchegg)


Lesenswert?

Mikke Mikke16 schrieb:
> @ Karl heinz Buchegger
> hab dir mal den kompletten Code per pn geschickt

Poste ihn bitte hier

von haya (Gast)


Lesenswert?

Hallo,

hier noch einige Anmerkungen:

"const" verwenden im Prinzip 2 Seiten

a) Anwender/Nutzer einer Funktion:
Der kann aus der const Deklaration ersehen, dass seine Variable, die er 
an eine Funktion übergibt, nicht verändert wird.
Wenn man dann fremde Funktionen aufrufen will versteht man diese dann 
eher, weil man sieht was verändert wird - und was nicht. Die 
Dokumentation ist ja meistens nicht besonders ausführlich :-(

b) als Entwickler/Bereitsteller einer Funktion:
Als Entwickler will man sich vor eigenen Fehlern schützen. Dann passt 
eben der Compiler für einen auf, dass man keine const Variablen ändert.

Das bedeutet, dass man const Parameter nicht an andere Funktionen - ohne 
const - weitergeben darf! Da geht dann meist das Problem los, dass 
"alter" Code oder Code "von Neulingen" eben die const Angaben nicht 
enthalten ...

b-1)
dann kann der Entwickler versuchen diese Funktion entsprechend 
anzupassen, und das const dort jeweils durchziehen - wenn der Code 
bereitsteht. Aber manchmal betrifft das eben fremde Bibliotheken, wo man 
nicht ändern kann (oder will).

b-2)
Einfacher oder überhaupt durchführbar ist dann dieses "const Korsett" 
durch einen "bösen" cast beim Aufruf zu entfernen.

Wenn man "lesbar" und "sicher(er)" programmieren will, sollte man also 
möglichst viele const einsetzen. Und bei der Auswahl der einzubindenden 
Bibliotheken Vorsicht walten lassen.

von Karl H. (kbuchegg)


Lesenswert?

Für C++ geht die Sache dann auf der Ebene der Member-Funktionen einer 
Klasse weiter. Auch hier wieder die Frage: Verändert eine Member 
Funktion das Objekt, für welches sie aufgerufen wurde, oder tut sie das 
nicht.

Nehmen wir als Beispiel eine Klasse, die einen Kreis repräsentiert.
Welche Member Funktionen hat die?
Da wird es eine Funktion geben, die zb den Radius des Kreises setzt bzw. 
liewfert. Und es wird Funktionen geben, die Fläche und Umfang berechnen.
1
class Circle
2
{
3
  public:
4
    Circle( double rad = 0.0 } : radius_( rad ) {}
5
6
    void radius( double rad )  { radius_ = rad; }
7
    double radius()            { return radius_; }
8
9
    double area()              { return radius_ * radius_ * PI; }
10
    double circumference()     { return 2 * radius_ * PI; }
11
12
  private:
13
    double radius_;
14
}

jetzt machen wir diese Klasse const-korrekt.
Daher die Fragestellung: Welche Funktionen kann ich aufrufen, ohne dass 
sich das Objekt verändert?

Na ganz sicher die radius() Funktion. Dadurch, dass ich einen Kreis nach 
seinem Radius frage, verändert sich der Kreis nicht. Ditto für area und 
circumference.

Was ist mit void radius( double rad )?
Rufe ich diese Funktion auf, dann verändert sich das Objekt. Ein Kreis 
mit einem Radius von 2.0 ist ein anderer als ein Kresi mit Radius 5.0

const-korrekt ist die Klasse also:
1
class Circle
2
{
3
  public:
4
    Circle( double rad = 0.0 } : radius_( rad ) {}
5
6
    void radius( double rad )    { radius_ = rad; }
7
    double radius() const        { return radius_; }
8
9
    double area() const          { return radius_ * radius_ * PI; }
10
    double circumference() const { return 2 * radius_ * PI; }
11
12
  private:
13
    double radius_;
14
}

und das wars dann schon. Jetzt ist die Klasse const korrekt.

Habe ich eine Funktion foo, die einen Kreis (zb per Referenz) erhält.
1
void foo( Circle & arg )
2
{
3
  arg.radius( 5.0 );
4
}

dann kann diese Funktion den Kreis verändern. Sagt sie ja auch selbt in 
ihrer Argumentliste: Der Kreis, den du mir gibst - Ich werde ihn 
verändern.
(Da ist kein const)

Auf der anderen Seite haben wir die Funktion bar
1
void bar( const Circle & arg )

Diese Funktion sagt explizit: Mach dir keine Sorgen. Der Kreis, den du 
mir übergibst - ich werde ihn nicht verändern.
Der Compiler überwacht diese Zusicherung. Machst du
1
void bar( const Circle & arg )
2
{
3
  arg.radius( 5.0 );
4
}

dann klopft dir der Compiler auf die Finger. Du hast zugesichert, arg 
nicht zu verändern. Die Funktion radius( double rad ) ist aber nicht 
const markiert. Man kann sie daher nicht aufrufen weil sie das Objekt 
verändert und es setzt eine Fehlermeldung.

Auf der anderen Seite
1
void bar( const Circle & arg )
2
{
3
  int Irgendwas;
4
5
  Irgendwas = arg.area() * 8.567;
6
}

ist völlig legal. area() trägt in der Klasse das const Attribut als 
Zusicherung, dass ein Aufruf von area() das Objekt nicht verändern wird. 
Es ist daher kein Problem diese Memberfunktion von arg aufzurufen. Die 
Zusicherung von bar an seinen Aufrufer wird dadurch nicht gebrochen. Das 
Objekt arg bleibt so wie es vor Aufruf von bar() war, auch wenn man 
zwischendurch das Objekt nach seiner Fläche befragt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.