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

TigerClaw25

unregistriert

1

15.07.2017, 11:31

Verkettete Listen

Hallo Zusammen,
ich habe eine Frage zu Listing9.5 (https://books.google.de/books?id=gXlcCwA…0listen&f=false)

Die Zeile "list<CRaumschiff*> lSchiffe" verstehe ich teilweise. Durch Templates kann man verschiedene Datentypen angeben, die in dem Fall in der Klasse "list" eingefuegt werden. Das verstehe ich soweit. Aber irgendwie kann ich mir das beim Datentyp einer Klasse,also CRaumschiff* nicht vorstellen. Zum einen haette ich das so geschrieben: list<CRaumschiff> *lSchiffe und zum anderen hoert mein Verständnis bei den normalen Templates mit Datentypen wie int oder float auf. Bei einer template klasse mit int kann ich z.b. bestimmte int Werte als Parameter an Konstruktor übergeben oder an Methoden durch Instanzen. Aber bei der Liste mit einem KlassenZeiger als datentyp komme ich vom Verständnis an meine Grenzen.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

15.07.2017, 12:01

Ich habe das Gefühl du hast mit 2 Konzepten ein wenig ein durcheinander. Das eine sind Typen und das andere Zeiger.

Zu Typen:

C-/C++-Quelltext

1
2
3
CRaumschiff raumschiff("Defender", 200);
int zahl = 5; // ist das gleiche wie:
int zahl(5);


Schau dir mal das Beispiel an. Das ist doch prinzipiell genau das gleiche. Dass man in der zweiten Zeile einfach eine Zahl zuweisen kann ist vor allem damit es einfacher leserlich ist, aber eigentlich ist es das gleiche wie wenn du eine eigene Klasse hast und da den Konstruktor explizit aufrufen musst um die Parameter anzugeben.

Wenn du nun eine Liste hast kannst du da jeden beliebigen Typ rein tun. Ob das jetzt ein int oder ein CRaumschiff ist spielt keine Rolle.

Zu den Zeigern:
Wenn du einen Typ hast gibt es immer die Möglichkeit, dass du eine Variable haben möchtest, die auf eine Instanz eines solchen Types zeigt. Dieser hat dann den Typ CRaumschiff*. Das kann man theoretisch noch weiter führen und Zeiger auf Zeiger haben, aber das lassen wir hier mal. CRaumschiff* ist aber auch lediglich ein Typ und den kann man auch mittels Template in eine Liste packen. Die Liste enhält dann konkret nicht CRaumschiff, sondern Zeiger auf CRaumschiff.

Wenn dir das noch nicht klar ist, würde ich empfehlen das Kapitel über Zeiger noch ein paar mal durchzulesen, damit rumzuspielen bis du eine Intuition bekommst was das genau ist. Dann sollte das Beispiel klarer sein.

TigerClaw25

unregistriert

3

15.07.2017, 13:01

"list<T*> lSchiffe" ist etwas verwirrend. lSchiffe ist also mein array. Und CRaumschiff mein Zeiger, dass ajf die verschiedenen Elemente zeigt. Wenn ich das so erklären würde?

Wahrscheinlich liegt das daran,dass es allgemein gehalten ist. Ich würde in der Klasse list bereits T* xyz deklarieren und dann eben nur list<CRaumschiff> schreiben. Waere ja dasselbe.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

15.07.2017, 14:03

Auf welche Auflage vom Buch beziehst du dich? Das erste Listing zu Listen (9.4) bezieht sich auf eine Liste auf den Typ CRaumschiff* und das zweite nicht. Ist in deiner Auflage vielleicht etwas anders. Aber in der die ich besitze steht dort konkret Zeiger auf CRaumschiff.
"list<T*> lSchiffe" ist etwas verwirrend.

Den Part finde ich in meiner Auflage nicht. Steht das wirklich so in deinem Buch? Ich kann mir das nicht ganz vorstellen.
lSchiffe ist also mein array. Und CRaumschiff mein Zeiger, dass ajf die verschiedenen Elemente zeigt.

Nein, eine Liste ist kein Array. Verkettete Listen können zwar intern mit einem Array umgesetzt werden, müssen sie aber nicht. Das spielt auch für dich keine Rolle. Wenn es wie ein Array wäre bräuchtest du ja keine Liste. Eine verkettete Liste ist einfach ein Container in den du etwas rein schieben kannst. Du kannst dir wie bei jedem STL Container die Iteratoren auf das erste und hinter das letzte Element besorgen. Damit kannst du deine Liste durchlaufen und auf die Elemente zugreifen. Auf Kopf und Ende der Liste kannst du direkt zugreifen. Was du aber im Vergleich zum Array nicht kannst ist direkt per Index auf ein Element zugreifen. Elemente kannst du an jeder beliebigen Stelle in der Liste einfügen. Das kannst du bei einem Array zum Beispiel nicht. Mal ein Beispiel:
Ein Array mit den Werten: [2, 3, 4, ?] wobei das Array die Größe 4 hat und der Wert nach der 4 nicht von dir selbst gesetzt wurde. Dort steht also irgendetwas was dich aber aktuell nicht interessiert (deshalb habe ich mal ein Fragezeichen hingeschrieben). Jetzt möchtest du gerne vor der 2 eine 1 einfügen. Dafür musst du jetzt selbst die restlichen Werte nach hinten kopieren um dann an die erste Position eine 1 zu schreiben. Danach hast du [1, 2, 3, 4].
Bei einer Liste geht das einfacher. Du hast zum Beispiel die Liste 2->3->4 und fügst jetzt einfach am Anfang die 1 an. Danach hast du 1->2->3->4 und gut ist. Einfach weil es ein völlig anderer Container ist.

Wahrscheinlich liegt das daran,dass es allgemein gehalten ist. Ich würde in der Klasse list bereits T* xyz deklarieren und dann eben nur list<CRaumschiff> schreiben. Waere ja dasselbe.

Ist es nicht. Wenn in der Klasse der Liste T* stehen würde könnte die Liste nur mit Zeigern umgehen. Wenn du jetzt eine Liste von einem nicht Zeiger Typ haben möchtest geht das nicht. Du könntest keine Liste von ints erstellen und auch keine Liste von CRaumschiffen. Nur eben von Zeigern darauf. Das möchte man ja nicht immer. In ein Template kannst du so erst mal alles rein stopfen. Und wie drakon schon sagte ist ein Zeiger auf etwas einfach ein weiterer Typ. Du kannst std::list<int> benutzen aber auch std::list<int*> oder std::list<int*****> wenn du denn möchtest. Das letzte mag erst mal ziemlich merkwürdig aussehen ist aber an sich möglich. Es ist eben ein Zeiger auf einen Zeiger auf einen Zeiger und so weiter. Brauchen wirst du so etwas nicht. Ich möchte damit nur zeigen dass ein Zeiger auf egal was wieder ein Typ ist.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

15.07.2017, 14:05

std::list<CRaumschiff*> l1; ist eine Liste, die als Einträge eben Zeiger auf Raumschiff-Instanzen enthält.
std::list<CRaumschiff>* l2; ist ein Zeiger auf eine Liste, die Raumschiff-Instanzen (keine Zeiger darauf) enthält.
std::list<CRaumschiff*>* l3; ist ein Zeiger auf eine Liste, die Zeiger auf Raumschiff-Instanzen enthält.
std::list<CRaumschiff***>*** l4; ist ein Zeiger auf einen Zeiger auf einen Zeiger auf eine Liste, die Zeiger auf einen Zeiger auf einen Zeiger auf Raumschiff-Instanzen enthält.
std::list<std::list<CRaumschiff*>*>* l5; ist ein Zeiger auf eine Liste, die Zeiger auf Listen mit Zeigern auf Raumschiff-Instanzen enthält.
Was ist daran verwirrend? ;)
Eine Liste ist übrigens etwas anderes als ein Array.
Weiterhin denke ich, dass du dir mehr eigene Gedanken machen und vor allem experimentieren solltest anstatt zu jeder Seite des Buches hier ein neues Thema aufzumachen ...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

15.07.2017, 14:44

Wahlweise nochmal weiter vorn lesen, was Zeiger genau sind, weil jedes Thema hier gefühlt nur deswegen existiert, weil er das Konzept noch nicht vollständig verstanden hat.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TigerClaw25

unregistriert

7

15.07.2017, 16:11

Ich glaube, dass ich mich falsch ausgedrückt habe. Nochmal von vorne. Templateklassen kenne ich:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
template <class T>
class CRaumschiff{
public:
T m_Var;
};

int main(){
CRaumschiff<int> Spieler;
return 0;
}

Dabei handelt es sich um ein einfaches Beispiel.

T ist ein Platzhalter, genau wie bei list<>. Auch das Thema Zeiger ist mir klar, wobei ich bei der Schreibweise etwas verwirrt war. Das Sternchen "*" kann wie folgt geschrieben werden: int* i; oder int * i; oder int *i;. Wobei ich die Schreibweise int *i; bevorzuge, weil das Sternchen einfach zur Variable gehört.

Bei der Schreibweise CRaumschiff<int*> Spieler habe ich einen Zeiger auf int-Werte der Instanz CRaumschiff. Das heißt "int* m_Var" bzw. aus Sicht meiner Schreibweise "int *m_Var".

Bei den Listen ist es ähnlich, wobei mein Datentyp jetzt CRaumschiffe* ist. Ich war etwas verwirrt, weil ich davon ausgegangen bin, dass die Template-Klasse mit "T*" statt mit "T" deklariert wird. Das war bei den Singleton's so, dass "T* m_Var" bereits in der Template-Klassen-Deklaration stand.

Ich glaube, dass mein Problem darin liegt, dass ich neue Themen mit alten vergleiche und so durcheinander komme. Einerseits ist es anfangs wichtig zu verstehen, wie alles eingesetzt wird. Aber ich möchte es auch verstehen ... Eventuell fehlt mir auch einfach die Gabe, mir das ganze logisch vorzustellen, schließlich liegt Programmieren nicht jedem.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

15.07.2017, 16:15

Ob man T oder T* nutzt, hängt vom Anwendungsfall ab. Eine Liste will Elemente enthalten, deren Typ du wählen können sollst. Folglich können das entweder Values sei wie int oder Pointer wie int*. Du entscheidest. Das Singleton aus dem Buch will dagegen klarmachen, dass es ein Einzelstück eines speziellen Typs herstellt. Z.B. von einem Menü. Aber intern erzeugt und speichert es ein Menü irgendwo auf dem Heap und deklariert intern deshalb T*.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TigerClaw25

unregistriert

9

15.07.2017, 21:35

Ich denke, ich habe es in etwa verstanden. Mit list<CKlasse*> l1; mache ich nichts anderes als was ich mit Arrays auch machen könnte. Ohne das ich die Vorteile von Listen berücksichtige. Würde ich den Befehl mit Arrays umsetzen wollen, müsste ich wir folgt vorgehen:
CKlasse *l1;
l1 = new CKlasse[Anzahl];

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

15.07.2017, 22:50

Nein, das ist nicht dasselbe.
Mit Arrays würdest du folgendes machen:
Klasse **l1;
l1 = new Klasse*[Anzahl];
Ein Array aus Pointern ist wohl näher an einer Liste aus Pointern als es ein Array aus Values wäre.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige