TStringList in Methode als return Wert zurückgeben ?
-
@Alexander: Nix für ungut, aber die herkömmliche Methode scheint mir hier - wegen des zwangweisen "new"-Erstellen der StringList als falsche methode. hier würde ich einen zeiger auf eine Instanz von TStringList der Funktion mitgeben.
-junix
-
Hallo
- TStringList an Methode uebergeben
- Methode verwendet (beschreibt) TStringListRueckgabe einer TStringList geht nur wenn Sie fuer die ganze Klasse (Form)
deklariert ist (private oder so)oder wennn sie PUBLIC ist
MfG
Klaus
-
geht schon:
#include "Unit1.h" #include <memory> using namespace std; //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; typedef auto_ptr<TStringList> TAutoStringList; TAutoStringList GetListe() { TAutoStringList temp(new TStringList) ; temp->Add("Hallo"); return temp; } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { TAutoStringList List= GetListe(); Memo1->Lines->AddStrings(List.get()); // hier wird der Speicher automatisch freigegeben da es sich um ein auto_ptr handelt } //---------------------------------------------------------------------------
-
junix schrieb:
(...) wegen des zwangweisen "new"-Erstellen der StringList als falsche methode. hier würde ich einen zeiger auf eine Instanz von TStringList der Funktion mitgeben.
Du meinst weil man u.U. vergessen koennte, diese Instanz mit delete wieder
zu loeschen?
Es vielleicht Geschmacksache (und ich habe darueber auch schon Diskussionen
gefuehrt), aber ich bevorzuge normalerweise eine Rueckgabe, da diese - z.B.
bei der Einarbeitung in ein bestehendes Programm - leichter zu erkennen
(oder zu verstehen) ist. Die andere Variante "riecht" fuer mich immer ein
bisschen nach Seiteneffekt.
Ich versuche prinzipiell Methoden "funktional" zu programmieren, also die
uebergebenen Variablen nicht zu veraendern und Ergebnisse per return zu-
rueckzugeben.
Wie gesagt, ist das vielleicht auch Geschmacksache und beide Wege haben
ihre Berechtigung...Gruss,
Alexander
-
Alexander Kempf schrieb:
junix schrieb:
(...) wegen des zwangweisen "new"-Erstellen der StringList als falsche methode. hier würde ich einen zeiger auf eine Instanz von TStringList der Funktion mitgeben.
Du meinst weil man u.U. vergessen koennte, diese Instanz mit delete wieder
zu loeschen?x-actly
Alexander Kempf schrieb:
Es vielleicht Geschmacksache (und ich habe darueber auch schon Diskussionen
gefuehrt), aber ich bevorzuge normalerweise eine Rueckgabe, da diese - z.B.
bei der Einarbeitung in ein bestehendes Programm - leichter zu erkennen
(oder zu verstehen) ist.... den Punkt halte ich für umstritten. Wenn die Funktion angemessen Dokumentiert ist, kommt es nicht wirklich darauf an, ob man nun einen Zeiger auf eine Instanz zurückliefert, oder die Instanz vom Aufrufenden verlangt. Letztere Variante hat vor Allem dann ihren Vorteil, wenn man die Funktion in eine LIbrary packen will. Ich finds aus Anwender (der Library) sicht immer etwas mühsam, wenn ich Speicher fregeben muss, den ich doch gar ned reserviert hatte.
Alexander Kempf schrieb:
Die andere Variante "riecht" fuer mich immer ein
bisschen nach Seiteneffekt.x-plain please.
Alexander Kempf schrieb:
Ich versuche prinzipiell Methoden "funktional" zu programmieren, also die
uebergebenen Variablen nicht zu veraendern und Ergebnisse per return zu-
rueckzugeben.Naja in solchen Situationen gebe ich immer einen Status zurück. Aber was machst du, wenn du mal mehr als einen Rückgabewert hast/brauchst?
-junix
-
Alexander Kempf schrieb:
Die andere Variante "riecht" fuer mich immer ein
bisschen nach Seiteneffekt.das sehe ich genau andersrum.
und ganz bestimmt ist es niht "funktional".du erstellst eine klasse die in einer methode ein objekt erzeugt und nicht löscht. imho das ist ein verstoß gegen OOP. eine klasse soll selbst um ihre daten/variablen etc. kümmern und nicht sich drauf verlassen, dass der benutzer der klasse weiss, dass mehtode xyz eine instance erzeugt, die nach dem aufruf der der methode gelöscht werden soll. was kümmert mich als Programmierer, was die klasse A oder funktion B intern macht?
gut das du die sachlage kennst, aber wenn jemand andrerer deine klassen utzen soll, oder du selbst in einem jahr?
wenn ich dagegen ein zeiger auf mein objekt an eine methode übergebe, dann weis ich auch 100% woher das objekt stamm und ob ich es löschen soll oder nicht.
-
hallo,
also leute in eurer diskussion sehe ich keinen sinn, warum macht er es nicht einfach so, so deleted wo erzeugt wird, und die liste wird per return zurückgegeben, wo ist das problem???
TStringList* GetList(TStringList* List) { List->Add("kukuk"); return List; } void __fastcall TForm1::Button1Click(TObject *Sender) { TStringList* mylist = new TStringList(); mylist = GetList(mylist); ShowMessage(mylist->Strings[0]); delete mylist; }
mfg
murphy
-
Hallo
@murphy
wenn du meinen Beitrag gelesen haettest - da steht genau das drin
(nur als Text - als Tip)- TStringList an Methode uebergeben
- Methode verwendet (beschreibt) TStringListMfG
Klaus
-
junix schrieb:
... den Punkt halte ich für umstritten.
Deswegen hatte ich darüber wohl auch schon Diskussionen geführt.
junix schrieb:
Wenn die Funktion angemessen Dokumentiert ist
Die Betonung liegt ganz klar auf "wenn". Ansonsten siehst Du sofort, daß ein
Zeiger auf ein Objekt zurückgegeben wird. Hast Du keinen Zeiger auf ein
Objekt der gleichen Klasse übergeben, wird's wohl in der Methode neu erstellt.junix schrieb:
Ich finds aus Anwender (der Library) sicht immer etwas mühsam, wenn ich Speicher fregeben muss, den ich doch gar ned reserviert hatte.
OK. Aber im anderen Fall mußt Du Dich auch drum kümmern, oder? Nur halt
vielleicht seltener...junix schrieb:
Alexander Kempf schrieb:
Die andere Variante "riecht" fuer mich immer ein
bisschen nach Seiteneffekt.x-plain please.
Xqgene schrieb:
und ganz bestimmt ist es niht "funktional".
Naja, ich denke da an funktionale Programmierung mit Sprachen wie z.B. Lisp.
Streng genommen sollte eine Funktion einer funktionalen Programmiersprache
keine der ihr übergebenen Variablen ändern, was ja hier logischerweise der
Fall wäre. Im "strengen" Lisp gibt's auch keine lokale Variablen innerhalb
der Funktion, was u.U. natürlich zu - nach prozeduralen Gesichtspunkten -
seltsamen Lösungswegen führen kann. Aber das ist vielleicht ein anderes Thema.junix schrieb:
Aber was machst du, wenn du mal mehr als einen Rückgabewert hast/brauchst?
Vielleicht einen struct oder eine Klasse zurückgeben? (Ja, ja, ich weiß das
ist mit Spatzen auf Kanonen geschossen...)
Im Prinzip fehlt in C++ die Möglichkeit, eine Methode mit mehreren Rückgabe-
werten sauber zu deklarieren, also jedem Argument noch ein "in" oder "out"
anzuhängen. Aber man kommt ja auch prima ohne aus...Xqgene schrieb:
du erstellst eine klasse die in einer methode ein objekt
erzeugt und nicht löscht. imho das ist ein verstoß gegen OOP.(...)Ich kann nicht erkennen, an welcher Stelle in der Anfangsfrage OOP auftaucht.
Ansonsten hast Du natürlich recht.
Aber um das ganze noch auf die Spitze zu treiben und einen wirklichen OOP-
Ansatz zu bekommen, könnte man auch eine eigene Klasse erstellen, die von
TStringList erbt und einen Konstruktor besitzt, der genau der Signatur der
Methode entspricht. Dieser Ansatz wäre wirklich ganz sauber, da hier genau
zu erkennen ist, wer eigentlich für das Reservieren und Freigeben von Speicher
verantwortlich ist. Aber ich bin mir nicht ganz sicher, ob das nicht vielleicht
u.U. etwas (nur geringfügig) zu viel Aufwand für die Sache ist (vorsichtig
ausgedrückt).Der Vorschlag von Andreas mit dem auto_ptr sieht aber doch ganz interessant
aus. Ist das denn performant (wie man neuerdings ja sagt)?Was man mit Sicherheit festhalten kann ist, daß Dokumentieren wichtig ist,
ein glückliches Händchen bei der Vergabe von Methoden- und Variablennamen
und man hat im Team schon halb gewonnen.Gruß,
Alexander
-
Naja, ich denke da an funktionale Programmierung mit Sprachen wie z.B. Lisp.
Streng genommen sollte eine Funktion einer funktionalen Programmiersprache
keine der ihr übergebenen Variablen ändern, was ja hier logischerweise der
Fall wäre. Im "strengen" Lisp gibt's auch keine lokale Variablen innerhalb
der Funktion, was u.U. natürlich zu - nach prozeduralen Gesichtspunkten -
seltsamen Lösungswegen führen kann. Aber das ist vielleicht ein anderes Thema.Wach auf. Du schreibst in C++.
Der Vorschlag von Andreas mit dem auto_ptr sieht aber doch ganz interessant
aus. Ist das denn performant (wie man neuerdings ja sagt)?Sagen wir so, du hast hier und da ein paar Prozessortakte mehr zu verarbeiten. Ins Gewicht wird es aber nicht fallen. Vom Prizip her ist im weitestens Sinne dieser auto_ptr ein garbage collector.
Gewöhn dich dran, andere Sprache andere Vorgehensweise. Wenn du C++ schreibst solltest du auch so handeln. In C++ sind Referenzen und Pointer normal. Und Referenzen und Pointer in Funktionsparameter sind auch normal. Es gibt nicht böses daran.