Objektorientierte Programm. < Softwaretechnik+Pro < Praktische Inform. < Hochschule < Informatik < Vorhilfe
|
Status: |
(Frage) beantwortet | Datum: | 21:49 Do 26.06.2008 | Autor: | Sir_Knum |
Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
Hallo,
könnte mir vielleicht jemand die folgenden Programmzeilen kurz erläutern. Was hat das CFlaeche** pf auf sich? Ein Zeiger auf Zeiger? Das new CFlaeche*[alloclen+=allocstep]; durchschaue ich ebenfalls nicht so recht. New reserviert Speicher. Aber was bedeutet das, was dahinter steht?
class CFlaechenListe
{
private:
CFlaeche** pf; //Liste der Geometriezeiger
int laenge; // belegte Laenge
int alloclen; // allokierte Länge des Arrays
int allocstep; // Schrittweite für Nachallokierung
public:
CFlaechenListe() { pf = NULL; laenge = 0; alloclen = 0; allocstep = 30; };
//Anhaengen an Ende der Liste
void append (CFlaeche* f)
{
if (alloclen < laenge+1) pf = new CFlaeche*[alloclen+=allocstep];
pf[laenge++] = f;
}
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 07:07 Fr 27.06.2008 | Autor: | bazzzty |
Hallo!
Du hast genau die richtigen Fragen gestellt, ich gehe das mal am Code durch.
> void append (CFlaeche* f)
Wir bekommen einen Pointer auf eine Fläche. Soweit klar.
> {
> if (alloclen < laenge+1) pf = new
> CFlaeche*[alloclen+=allocstep];
> Was hat das CFlaeche** pf auf sich? Ein
> Zeiger auf Zeiger?
Wir speichern die Pointer in einem Array ab.
Wir speichern also Elemente vom Typ CFlaeche* in einem Array ab. Normalerweise sieht das so aus:
Object* arrayName = new Object[arrayLaenge]
Warum Object*? Weil ein Array in C++ dasselbe ist wie ein Zeiger auf das erste Element. (Und, btw: new reserviert im allgemeinen nicht nur Speicher, sondern ruft auch Konstruktoren auf, hier allerdings nicht).
Jetzt ist zumindest klar, warum pf vom Typ CFlaeche** ist.
> Das new CFlaeche*[alloclen+=allocstep];
> durchschaue ich ebenfalls nicht so recht. New reserviert
> Speicher. Aber was bedeutet das, was dahinter steht?
Bei new "CFlaeche*[alloclen+=allocstep]" wird dann noch ausgenutzt, daß jede Zuweisung immer auch Ausdruck ist. Das heißt, es ist möglich, alloclen zu erhöhen und das Ergebnis gleich noch als Länge des neuen Arrays zu verwenden.
Genauso dürfte man schreiben.
alloclen = alloclen + allocstep
new CFlaeche*[alloclen]
> pf[laenge++] = f;
> }
Hier wird dasselbe gemacht, allerdings steht hier
pf[laenge] = f;
laenge=laenge+1;
Damit das ganze ein dynamisches Array wird, müßten allerdings nach um den new-Aufruf herum noch die alten Pointer umkopiert werden.
Ich hoffe aber, daß das kein Lehrstück in C++-Programmierung sein soll. Das ist nämlich kein C++, sondern eher das verpönte "C++--", wie ihn C-Programmierer schreiben, die nie richtig C++ gelernt haben.
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 20:32 Fr 27.06.2008 | Autor: | Sir_Knum |
Hallo,
das war ja schon eine ziemlich ausführliche Erklärung-danke. Durch
new CFlaeche*[alloclen+=allocstep]; wird also Speicherplatz für ein Array der Länge alloclen+=allocstep mit Zeigern auf
CFlaeche als Elemente bereitgestellt, richtig? Dann wird der
übergebene Zeiger f in das neue Array an die Stelle laenge+1 gepackt.
Ich hoffe, ich habe das jetzt einigermaßen verstanden.
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 22:09 Fr 27.06.2008 | Autor: | bazzzty |
> Durch
> new CFlaeche*[alloclen+=allocstep]; wird also Speicherplatz
> für ein Array der Länge alloclen+=allocstep mit Zeigern auf
> CFlaeche als Elemente bereitgestellt, richtig? Dann wird
> der > übergebene Zeiger f in das neue Array an die Stelle
> laenge+1 gepackt.
> Ich hoffe, ich habe das jetzt einigermaßen verstanden.
Ja, genau. Damit das ganze wirklich eine "sinnvolle" Implementierung eines dynamischen Arrays wäre, müßte man allerdings die Elemente aus dem alten Array noch umkopieren.
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 13:03 Sa 28.06.2008 | Autor: | Sir_Knum |
Also,das soll ein C++ Musterprogramm sein. Es ist während eines C++ Praktikums entstanden. Das Problem ist nur, dass unser Prof. so schnell war, dass man teilweise nur abtippen konnte. Das Array soll dynamisch sein. Hier die Erweiterung:
#include "Flaeche.h"
template <class T>
T expand(T p,const int& oldlen,const int& newlen)
{
//neuen Bereich allokieren
T pnew = (T)new void*[newlen];
//Umspeichern des bisherigen Bereiches
for (int i=0; i<oldlen; i++) pnew[i] = p[i];
//Löschen des alten Bereiches
delete[] p;
return pnew;
}
...
...
class CFlaechenListe
{
private:
...
void append (CFlaeche* f)
{
if (alloclen < laenge+1)
pf = expand(pf, laenge, alloclen+=allocstep);
pf[laenge++] = f;
}
}
Ich verstehe noch nicht das expand(T p,const int& oldlen,const int& newlen). Ist T ein Datentyp??
Dann das T pnew = (T)new void*[newlen]; Hier wird Speicherplatz für ein Array von Zeigern, die auf einen beliebigen Datentyp zeigen, reserviert? Was soll denn das T in Klammern und das T vor pnew????????????
|
|
|
|
|
Hi,
T steht hier einfach für irgendeinen Datentyp. expand ist damit eine generische Funktion. Somit kannst du in deinem dynamischen Array jeden Datentyp speichern, also auch (anders als z.B. bei Java) Atomare Datentypen.
mfG Michi
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 18:51 Sa 28.06.2008 | Autor: | Sir_Knum |
Okay,
T steht also für einen beliebigen Datentyp.Wäre gut, wenn mir jemand noch folgende Fragen beantworten könnte. Aber warum steht das T vor pnew und dann noch mal in Klammern?
Steht T immer für einen beliebigen Datentyp oder muss das irgendwo deklariert werden?
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 21:51 Sa 28.06.2008 | Autor: | bazzzty |
> Okay,
> T steht also für einen beliebigen Datentyp.Wäre gut, wenn
> mir jemand noch folgende Fragen beantworten könnte. Aber
> warum steht das T vor pnew und dann noch mal in Klammern?
> Steht T immer für einen beliebigen Datentyp oder muss das
> irgendwo deklariert werden?
Lustig ist, daß die erste Frage die Antwort auf die zweite ist.
Ich erkläre vielleicht mal ganz kurz was zu Templates.
Wenn man Datenstrukturen (wie dynamische Arrays) implementiert, dann kann man das natürlich für jeden Typ (wie CFlaeche*) einzeln tun. Das ist aber ein völlig unnötiger Aufwand. Stattdessen schreibt man Templates. Die zeichnen sich dadurch aus, daß man (mithilfe der spitzen Klammern) ankündigt, daß in diesem Template ein Bezeichner (hier T) für einen beliebigen Typ stehen kann.
Da könnte also statt T auch irgendwas anderes stehen: In den spitzen Klammern ist die Deklaration des Template-Parameters, der dann als Typ im Template verwendet werden kann.
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 19:08 So 29.06.2008 | Autor: | Sir_Knum |
Hallo,
zu T pnew = (T)new void*[newlen]; das T vor pnew legt also fest, dass pnew vom Datentyp T ist. Das (T) ist ein casting, sodass der Rückgabewert von new auch vom Typ T ist. Soweit alles richtig??
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 20:38 Mo 30.06.2008 | Autor: | Sir_Knum |
Hallo,
wenn an der Frage etwas unverständlich ist, biite sagen. Meine Klausur nähert sich nämlich in großen Schritten.
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 05:40 Di 01.07.2008 | Autor: | bazzzty |
> Hallo,
> zu T pnew = (T)new void*[newlen]; das T vor pnew legt also
> fest, dass pnew vom Datentyp T ist. Das (T) ist ein
> casting, sodass der Rückgabewert von new auch vom Typ T
> ist. Soweit alles richtig??
Ja. Zumindest so ungefähr. Der Rückgabewert ist natürlich nur irgendein Pointer. Aus Compilersicht gibt new void*[] etwas vom Typ void** zurück, um das einer Variable vom Typ T zuweisen zu dürfen, muß man casten. Der Wert bleibt aber ein Pointer.
Ich halte das nach wie vor nicht für guten Code. Der Template-Parameter "T" ist nicht eingeschränkt, aber der Code funktioniert natürlich nur, wenn T vom Typ "Klasse**" ist, weil sonst das Casting nicht geht...
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 09:18 Di 01.07.2008 | Autor: | Sir_Knum |
Okay, dann habe ich erst mal alles verstanden. Wenn der Code nicht so gut ist- ist dann das Problem vom Prof.
Danke nochmal für die Hilfe.
|
|
|
|