PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfängerfrage zu Klassen



Ischum
03.02.2017, 11:35
Hallo,
ich lerne seit paar Monaten C++ (C++11).
Nun habe ich eine Frage zum Thema Klassen:
Ich habe eine Klasse "Auto". Daraus erstelle ich 2 Instanzen, dessen Adresse ich einem Zeiger übergebe (z.B: zeiger1 für auto1, zeiger2 für auto2).

Nun rufe ich die Methode "Reifendruck" über die Zeile
auto1->reifendruck(20);
auf
Diese Methode erhöht den Reifendruck um 20% mit der Zeile in der Methode
reifendruck = reifendruck + 20;

Alles funktioniert wunderbar, aber nun zu meiner Frage:
Ändert die Zeile "reifendruck = reifendruck + 20;" den Reifendruck von auto1 oder auto2? Denn ich habe in der Methode "auto::reifendruck" ja nicht explizit angegeben, das der Reifendruck an auto1 oder auto2 verändert werden soll, sondern ich habe NUR angegeben das der reifendruck erhöht werden soll (ohne Angabe der Instanz auto1).
Nun frage ich mich: woher weiß der Compiler, von welchem Auto ich den Reifendrück erhöhen möchte. Meine einzige Idee ist: Der Compiler weiß es von der Anweisung "auto1->reifendruck(20);", hier wird die Methode "reifendruck" ja über die Instanz "auto1" aufgerufen, daher wird auch "reifendruck" von auto1 erhöht, statt von auto2 oder sontigem.
Das heißt für mich: Wenn ich eine Methode über eine bestimmte Instanz aufrufe, in dem Beispiel "auto1", dann werden innerhalb der Methode nur Änderungen der Attribute an auto1 unternommen, und nicht an auto2. Wenn ich theoretisch über die Methode (aufgerufen von auto1) ein Attribut von auto2 ändern will, dann müsste ich aus dieser Methode, eine Methode über auto2 aufrufen wie z.B. auto2->methodenname(...);

Ist das so richtig?
ich hoffe ihr versteht was ich meine... Sonst bitte nachfragen. danke!

Ceos
03.02.2017, 12:20
das nennt man Scope, solange du dich innerhalb von Geschweiften Klammern befindest, hast du einen geschlossenen Scope, darin sind alle Variablen die du anlegst quasi privat ​und außerhalb der geschweiften Klammer nicht zugänglich ....

Deshalb ist es auch ungemein Wichtig, dass du innerhalb eines Scopes (Methode oder Schleife) NIEMALS denselben Variablennamen wählst, wie er bereits außerhalb des Sceope bereits existiert. Du kannst innerhalb eines Scopes auf Variablen im Darüberliegenden Scope zugreifen und das ist dann zum einen unleserlich und zum anderen unsicher, weil du nicht exakt vorhersagen kannst WELCHE Variable du manipulierst.

Und zu Klassen und Instanzen, gilt folgendes anschauliches Beispiel:

Eine Klasse ist eine Bauanleitung, die beschreibt was im Bezug auf einen bestimmten Bezugspunkt (der Pointer beim new) wo an welcher Stelle liegt. Wenn ich also 2 mal new mache, habe ich 2 Instanzen an unterschiedlichen Stellen im Speicher. Wenn ich also jetzt auto1->reifendruck(); aufrufe, rufe ich die methode im Objekt auto1 auf und auto2 bleibt in seinem eigenen Speicherbereich davon unberührt.

shedepe
03.02.2017, 12:30
Nun du erstellst deine Klasseninstanz ja so:



Auto* A = new Auto();


A ist ein Pointer vom Typ Auto. Genauso wie


int * b = new int();

ein Pointer vom Typ int ist.

D.h. der Compiler weiß an der Stelle wenn du A verwendest: Heh das ist der Typ Auto.

Zu deiner Frage:
Ich gehe davon aus du hast in deiner Klasse Auto eine Methode namens "reifendruck" die ein Attribut der Klasse Aut namens "reifendruck" erhöht. (Btw. Bitte benenne Methoden danach was sie machen. Also z.B erhoeheReifendruck())
Nun machst du die Aufrufe:


Auto* auto1 = new Auto();
Auto* auto2 = new Auto();
auto1->reifendruck();
auto2->reifendruck();


Was passiert dabei im Hintergrund:
1. Du arbeitest jeweils auf einer eigenen Instanz der Klasse Auto. D.h. der Compiler hat beim Aufruf "Auto* auto1 = new Auto()" extra Speicherplatz für die Attribute der neuen Instanz der Klasse Auto reserviert. Deshalb muss man danach mit delete auch den Speicher wieder freigeben.
2. Wenn du nun aufrufst "auto1->reifendruck();" Weiß der Compiler zum einen: Das ist der Typ Auto, diese Klasse hat eine Methode "reifendruck". Zum anderen weiß der Compiler: Das ist die Instanz "auto1". Also muss ich die Methode reifendruck im Kontext der Daten von auto1 aufrufen.

Also eine kurze Zusammenfassung:
Wenn du zwei Instanzen erstellst und in Methoden der Klasse auf Instanzvariablen (Attribute) zugreifst, dann änderst du nur die Attribute der ausgewählten Instanz.
Wenn du Instanzübergreifend eine Variable haben willst (Wovon in 99,99% der Fälle abzuraten ist, und die Notwendigkeit einer solchen Variable auf eine schlechte Architektur schließen lässt) kannst du die Variable statisch als Klassenvariable anlegen. D.h. diese existiert innerhalb deines Programms nur einmal und alle Methoden die auf diese zugreifen Ändern diese eine Variable.

@Ceos Das ist nur indirekt eine Sache des Scopes meiner Ansicht nach ;)
Ein Sache des Scopes wäre eher sowas:


int main(void)
{
int a = 0;
{ //Scopes werden durch Klammern markiert (Auch die {} der int main(void) sind ein Scope)
a= 100;
int b = 10;
std::cout << b << std::endl;
std::cout << a << std::endl; //Funktioniert
} //Wir verlassen den Scope
std::cout << b << std::endl; //Gibt compiler fehler

}

Ceos
03.02.2017, 12:52
ich weis auch nicht was mein Hirn da fabriziert hat mit den Scopes asl ich es getippt habe ... aber ich Empfangd es dennoch als eine brauchbare Lektion und hab es nicht entfernt XD

Der eigentlich brauchbare Teil kam ja danach :P

Ischum
06.02.2017, 13:47
Danke an euch, vorallem an shedepe für die ausführliche Erklärung!