Anfänger: Array aus Strings (System::String)



  • Danke für die ausführliche Antwort!

    asc schrieb:

    C++/CLI ist jedenfalls jenseits von gut und böse, und hat eigentlich nur Sinn als Brücke zwischen "nativer" und "managed" Welt. Entweder programmierst du C++ oder C#/VB.net, aber bitte nicht C++/CLI, gerade nicht als Anfänger.

    Okay, aber jetzt mal ganz doof gefragt: "Normales" C++ lässt sich ja auch innerhalb C++/CLI programmieren, hab ich jetzt auch schon so gemacht. Dann ist doch der einzige CLI-Berührungspunkt eben das GUI, wenn man von den .NET-Klassen die Finger lässt.

    Meine Sorge ist:
    Nicht lachen, aber ich habe bis vor kurzem nur mit einem ganz alten Basic (ohne GUI) programmiert. 15 Jahre lang, mit sehr, sehr vielen Projekten.

    Ich komme also einfach gar nicht aus einer nicht-objektorientierten Richtung. Jetzt habe ich ein Buch über C++ schon ziemlich weit durchgearbeitet, und bin froh, daß es nicht soo kompliziert ist und vor allen Dingen auch, daß ich da "meine Problemlösungs-Methoden" eigentlich ganz klassisch anwenden kann, wie bisher - abgesehen mal von der GUI.

    Daher wäre jetzt nochmal mit c# neu anfangen doch ein bischen doof, und vielleicht auch unnötiger Aufwand. Kann man es nicht auch so sehen? Eben normales C++ schreiben, die .Net Klassen einfach nicht nutzen - abgesehen eben von Windows Forms, als Schnittstelle zur Aussenwelt?

    asc schrieb:

    Eine Excelansteuerung ist keine triviale Aufgabe, auch wenn .Net das ganze erleichtert.

    Da hast Du mich falsch verstanden: Ich will ja gar keine Excelansteuerung... Ich will ein gemischtes Array, und ich fänds schön, wenn ich Sachen wie Sortierungen und Elemente hinzufügen/wegnehmen und Speicherverwaltung nicht alle zu Fuß programmieren müsste (also wenn es für soetwas Klassen/Klassenfunktionen gäbe). Zur Not mache ich das eben auf die harte Tour 😉



  • Okay, aber jetzt mal ganz doof gefragt: "Normales" C++ lässt sich ja auch innerhalb C++/CLI programmieren, hab ich jetzt auch schon so gemacht. Dann ist doch der einzige CLI-Berührungspunkt eben das GUI, wenn man von den .NET-Klassen die Finger lässt.

    Es mischt sich automatisch, wenns mit /clr Kompiliert wird. Es werden für Funktionen zwei Einsprungspunkte erzeugt (einen managed / einen native), etc.

    Simon



  • Hallo maugli,

    für reines C++ gibt es die STL (Standard Template Library) und dessen Container-Klassen: std::vector<>, std::list<>, std::map<> etc. Dort kannst du dann auch Werte dynamisch hinzufügen, löschen und die ganze Liste sortieren lassen.

    Du solltest dich also wirklich entscheiden, ob du natives C++ willst oder aber generell das .NET-Framework benutzen willst. Und für letzteres ist C# bzw. VB.NET die passende Sprache (da du ja von BASIC kommst, wäre also der Umstieg auf VB.NET vllt. das Richtige).



  • Th69 schrieb:

    Hallo maugli,

    für reines C++ gibt es die STL (Standard Template Library) und dessen Container-Klassen: std::vector<>, std::list<>, std::map<> etc. Dort kannst du dann auch Werte dynamisch hinzufügen, löschen und die ganze Liste sortieren lassen.

    Du solltest dich also wirklich entscheiden, ob du natives C++ willst oder aber generell das .NET-Framework benutzen willst. Und für letzteres ist C# bzw. VB.NET die passende Sprache (da du ja von BASIC kommst, wäre also der Umstieg auf VB.NET vllt. das Richtige).

    Okay, und jetzt die meinerseits entscheidende Frage:

    Spricht denn irgendetwas dagegen, in Microsofts Visual Studio (C++) eben natives C++ mithilfe der STL-KLassen zu programmieren, und .NET eben nur für die Nutzerinteraktion zu verwenden?



  • maugli schrieb:

    Okay, und jetzt die meinerseits entscheidende Frage:

    Spricht denn irgendetwas dagegen, in Microsofts Visual Studio (C++) eben natives C++ mithilfe der STL-KLassen zu programmieren, und .NET eben nur für die Nutzerinteraktion zu verwenden?

    Und hier die entscheidende Antwort:
    http://www.c-plusplus.net/forum/263084



  • theta schrieb:

    Und hier die entscheidende Antwort:
    http://www.c-plusplus.net/forum/263084

    Ich lese die Antwort auf meine Frage aus den dort aufgeführten Argumenten aber nicht unbedingt heraus. z.B. müsste es doch möglich sein, Funktionen und Klassen ausserhalb der form.h zu definieren, und dann kann man von mehreren Form-Elementen darauf zugreifen, ohne sich mit CLI auseinanderzusetzen oder "Code zu mischen", also ohne z.B., wie im zitierten Artikel, ohne "einen STL-Vector in ein CLR Objekt reinzustopfen". Man braucht die CLR-Objekte doch nicht unbedingt, wenn man mit STLs arbeitet. Oder mache ich da einen Denkfehler?



  • Du kannst alles machen. Dazu musst Du aber zuerst C++ verstanden haben.

    Es ist leider eine Untugend, dass die Methoden in der Form*.h Datei implementiert sind... die müssen in der cpp-Datei implementiert werden, dann wird vieles einfacher.



  • Von C++ hab ich schon ein bischen was verstanden. Nur die Organisation des Codes in den verschiedenen Dateien ist mir noch ein bischen schleierhaft.

    Was genau meinst Du mit Methoden? Die .Net-Klassenfunktionen?



  • Ja. Bitte verschiebe die *Implementierung* der Methoden (zu Member-Funktion sagt man Methoden), in die CPP-Datei (die Du auch noch zuerst anlegen musst).

    Damit umgehst Du viele Probleme...



  • Du weisst nichts über die Trennung von Header und Source Files und hast die Absicht native C++ und managed C++ zu mischen.. ist so wie wenn Du ohne Airbag und Gurte mit 180km/h gegen auf eine Wand zufährst.



  • Vielleicht kann mir jemand über die Zusammenhänge ein bischen auf die Sprünge helfen.

    Für euch ist das wahrscheinlich ein Klacks, also ich hoffe auf ein, zwei Sätzchen, die etwas Licht ins Dunkel bringen...

    Ich habe zum Test eine einfache Klasse in einer eigenen .h-Datei deklariert, und eine zugehörige Klassenfunktion in eine cpp gepackt.
    Diese .h-Datei habe ich in die Projekt.cpp inkludiert, in der die main-Funktion steht.

    1. Frage: Um beide Elemente (Deklaration in der h und Funktionsdefinition in der cpp) habe ich eine Namespace-Klammer mit gleichem Bezeichner gesetzt. Diesen nutze ich auch zum Aufruf. Es funktioniert, aber ist das richtig/okay/üblich so?

    Ich habe nun ein Objekt dieser Klasse vor dem Aufruf des Formulars innerhalb der Hauptprojektdatei "Projekt.cpp", genauer, innerhalb der main() Funktion und vor dem Aufruf des "Form"-Objektes erzeugt, und konnte die von mir definierte Klassenfunktion auch erfolgreich ausführen. (getestet hab ich das mittels einer globalen Variablen, die ich innerhalb meines Formulars zur Überprüfung ausgeben ließ)

    Nach der Erzeugung des Objektes wurde ja "form1" erzeugt:

    Application::Run(gcnew Form1())

    2. Frage: Vom Eventhandler in Form1.h aus gesehen ist mein Objekt, welches ich in der *.cpp erzeugt habe, unsichtbar. Wieso? Lässt sich ein Objekt auch so erzeugen, daß es global sichtbar ist?

    3. Frage: Um innerhalb von form1.h ein Objekt erzeugen zu können, musste ich erneut die eigene Klassen-Deklaration .h einbinden, die auch schon in die projekt.cpp eingebunden hatte. Es funktioniert zwar - aber ist das richtig/okay/üblich so?

    Ich weiß, ist alles sehr newbiemässig... Ich danke für Antworten!



  • 1. Frage: Um beide Elemente (Deklaration in der h und Funktionsdefinition in der cpp) habe ich eine Namespace-Klammer mit gleichem Bezeichner gesetzt. Diesen nutze ich auch zum Aufruf. Es funktioniert, aber ist das richtig/okay/üblich so?

    Das kannst Du so machen. Ich qualifiziere meistens voll, auch in den CPP Files.

    2. Frage: Vom Eventhandler in Form1.h aus gesehen ist mein Objekt, welches ich in der *.cpp erzeugt habe, unsichtbar. Wieso? Lässt sich ein Objekt auch so erzeugen, daß es global sichtbar ist?

    Ja (allerdings nur für natives C++), das wären dann globale Variablen, welche aber ihre Nachteile haben und vermieden werden sollten.

    Zwei Lösungsvorschläge:
    1. Instanziere doch dein Objekt erst in Form1. Es ist dann ein Member der Form1 und Du kannst innerhalb der Form1 bequem darauf zugreifen.
    2. Du kannst es ausserhalb der Form1 erzeugen und machst das Objekt auf irgendeine Art dem Form1 Objekt bekannt. Z.B. indem Du es via Konstruktur übergibst oder einer Methode (bzw. Property) von Form1. Natürlich nur eine Referenz / Pointer.

    3. Frage: Um innerhalb von form1.h ein Objekt erzeugen zu können, musste ich erneut die eigene Klassen-Deklaration .h einbinden, die auch schon in die projekt.cpp eingebunden hatte. Es funktioniert zwar - aber ist das richtig/okay/üblich so?

    Ja, das ist gut so. Manchmal tuts auch eine Vorwärtsdeklaration im Header File und das Include wird erst in der Source Datei gemacht. Lies darüber einfach mal.

    $imon



  • Danke für die Antwort, die etwas Licht ins Dunkel bringt.

    theta schrieb:

    Ja (allerdings nur für natives C++), das wären dann globale Variablen, welche aber ihre Nachteile haben und vermieden werden sollten.

    Ich verstehe, daß diese Empfehlung Sinn macht. Ich fragte hauptsächlich deswegen, um die Zusammenhänge zu verstehen.

    theta schrieb:

    2. Du kannst es ausserhalb der Form1 erzeugen und machst das Objekt auf irgendeine Art dem Form1 Objekt bekannt. Z.B. indem Du es via Konstruktur übergibst oder einer Methode (bzw. Property) von Form1. Natürlich nur eine Referenz / Pointer.

    Okay, hier möchte ich mal nachhaken, ob ich es richtig verstanden habe:

    Zu Möglichkeit 1: Wenn ich ausserhalb von form1.h ein Objekt erzeuge, könnte ich also einen Pointer auf dieses Objekt dem Code in form1.h zukommen lassen, über den Konstruktor von form1? Also beim Erzeugen von Form1?

    Also hier hin?

    Application::Run(gcnew Form1(Pointer_auf_Objekt));
    

    Und hier hin?

    Form1(Pointer_auf_Objekt)
    		{
    			InitializeComponent();
    
    			// UND den übergebenen Pointer HIER dann irgendeiner privaten Pointer-Variablen innerhalb von Form1 zuweisen?
    			//
    			//
    		}
    

    Zur Möglichkeit 2, meinst Du damit: Ich könnte also eine Funktion in der Klasse "form" programmieren, die einen Pointer für dieses Objekt annimmt, und die ich zur Übergabe von ausserhalb aufrufen kann? (beispielsweise von einer aus "form1" dort aufgerufenen "form2", die an "form1" auf diese Art Rückgabewerte liefert, bevor sich form2 beim Schließen selbst plattmacht?)

    Neue Frage 1: Wie darf ich mir das vorstellen, Objekte (z.B. ein std::string) können Member von anderen Objekten (z.B. form1) sein? Kann man Objekte selbst einem anderen Objekt übergeben, d.h. "die sind dann dort und nur dort", oder eben nur einen Pointer auf ein Objekt, und im Prinzip könnten alle Objekte (z.B. auch form2) auf dieses Objekte zugreifen, wenn sie nur den passenden Pointer darauf irgendwoher bekommen?

    Neue Frage 2: Jochen Kalmbach schreibt ja "Bitte verschiebe die *Implementierung* der Methoden (zu Member-Funktion sagt man Methoden), in die CPP-Datei (die Du auch noch zuerst anlegen musst)."

    Welche Methoden meint er? form1 hat (soweit ich das im Code sehe/verstehe) standardmässig keine Methoden, die in der form1.h implementiert wären, ausser dessen Konstruktor, Destruktor und die Funktionen, die von den Eventhandlern aus aufgerufen werden. Meint er letztere?

    Neue Frage 3:

    Dieser Codeschnipsel hier (automatisch vom FormDesigner generiert) scheint ja ein Objekt "Eventhandler" für einen Knopfdruck zu erzeugen:

    this->evaopenbutton->Click += gcnew System::EventHandler(this, &Form1::evaopenbutton_Click);
    

    Ich verstehe auch, daß der Konstruktor dieses Eventhandlers offenbar übergeben bekommt, welche Funktion er nachher aufrufen soll. Wie könnte man umgangssprachlich ausdrücken, was davor steht (also "this->evaopenbutton->Click += "), und was diese Zeile also insgesamt bewirkt?

    (Meine Theorie: Die Adresse dieses neu erzeugten Eventhandlers landet im Attribut "Click" des Objektes "evaopenbutton". Stimmt das so? Heisst das, daß gcnew immer einen Pointer auf das gerade frisch erzeugte Objekt als Funktionswert zurückgibt?)



  • maugli schrieb:

    Zu Möglichkeit 1: Wenn ich ausserhalb von form1.h ein Objekt erzeuge, könnte ich also einen Pointer auf dieses Objekt dem Code in form1.h zukommen lassen, über den Konstruktor von form1? Also beim Erzeugen von Form1?

    und

    maugli schrieb:

    // UND den übergebenen Pointer HIER dann irgendeiner privaten Pointer-Variablen innerhalb von Form1 zuweisen?

    Ja, genau so meinte ich das.

    maugli schrieb:

    Zur Möglichkeit 2, meinst Du damit: Ich könnte also eine Funktion in der Klasse "form" programmieren, die einen Pointer für dieses Objekt annimmt, und die ich zur Übergabe von ausserhalb aufrufen kann? (beispielsweise von einer aus "form1" dort aufgerufenen "form2", die an "form1" auf diese Art Rückgabewerte liefert, bevor sich form2 beim Schließen selbst plattmacht?)

    Das meinte ich so:

    ref class MyObject;
    
    ref class Form1 : Form
    {
    public:
       void SetMyObject(MyObject^ myObject)
       {
          // ...
       }
    };
    

    Einfach eine Methode anstelle des Konstruktors. Dasselbe mit Properties. Der Rest deines Zitates ist etwas wirr...

    Zu Neue Frage 2: Einfach trennen was zu trennen ist.
    Zu Neue Frage 3: Lies nach was Events und Delegates sind (http://msdn.microsoft.com/en-us/library/edzehd2t.aspx)



  • theta schrieb:

    Ja, genau so meinte ich das.

    Okay, dann hab ich das offenbar kapiert. 🕶

    theta schrieb:

    ref class MyObject;
    
    ref class Form1 : Form
    {
    public:
       void SetMyObject(MyObject^ myObject)
       {
          // ...
       }
    };
    

    Ja, so hab ichs auch gemeint. Klappt das gleiche Spiel denn auch mit einem Pointer auf ein unmanaged Objekt? (dann mit * statt ^)

    theta schrieb:

    Der Rest deines Zitates ist etwas wirr...

    Ich meinte Folgendes: Angenommen ich habe zwei Forms, und instantiiere form2 aus form1 heraus (beispielsweise ausgelöst von einem Buttonklick auf form1). Dann könnte ich in form2 doch ein beliebiges Daten-Objekt erzeugen, welches ich durch einen Funktionsaufruf ("form1->SetMyObject()") in form1 bekannt mache, bevor form2 geschlossen wird.
    (mit return könnte man den Pointer auf das neue Objekt vermutlich ja auch zurückgeben, aber es geht mir ums Prinzip, ob das auch über einen Funktionsaufruf möglich wäre.)

    theta schrieb:

    Einfach trennen was zu trennen ist.

    Ganz konkret: Welche Methoden meint er, die in form1.h ungünstigerweise vom Formdesigner implementiert werden? Ich sehe - wie gesagt - hier innerhalb dieser Datei nur die Funktionen, die eben von den Eventhandlern aufgerufen werden. Meint er die, oder was anderes?

    theta schrieb:

    Zu Neue Frage 3: Lies nach was Events und Delegates sind (http://msdn.microsoft.com/en-us/library/edzehd2t.aspx)

    Alles klar, mach ich.

    Danke für die Zeit, die Du Dir nimmst 👍 so langsam lichtet sich bei mir der Vorhang, und ich begreife die Sachen ein bischen, die in der form1.h stehen.



  • Ich sehe - wie gesagt - hier innerhalb dieser Datei nur die Funktionen, die eben von den Eventhandlern aufgerufen werden. Meint er die, oder was anderes?

    Ja, die. Auch alle andern, die möglich sind. Der vom Designer genrierte Code (in der entsprechenden Region) geht nicht.



  • theta schrieb:

    Ich sehe - wie gesagt - hier innerhalb dieser Datei nur die Funktionen, die eben von den Eventhandlern aufgerufen werden. Meint er die, oder was anderes?

    Ja, die. Auch alle andern, die möglich sind. Der vom Designer genrierte Code (in der entsprechenden Region) geht nicht.

    Mit "alle andern" meinst Du das, was ich ggf. selbst noch reinprogrammieren will?

    Zur Durchführung... denn ich kann die Funktionen ja nicht einfach nur ausschneiden. Soll ich also nur eine Deklaration dieser Funktion(en) in der ursprünglichen .h lassen, also beispielsweise so:

    private: System::Void openFileDialog1_FileOk(System::Object^  sender, System::ComponentModel::CancelEventArgs^  e);
    

    ...und die Implementierung, also den Code, in eine cpp verfrachten, in welche die form1.h ihrerseits inkludiert wird?

    Dann gibt es ja ein Problem: Die in die cpp ausgelagerte Funktion steht dann ja ausserhalb der Klassenklammern, die in der .h stehen. Wie müsste die zugehörige Funktion in der cpp korrekt aussehen, kann mir das jemand mal ganz kurz sagen?

    Bei einfachen Klassen-Funktionen, die in einer cpp implementiert werden, schreibt man ja z.B.:

    void klasse::funktion() {Code};
    

    ...muß das also dementsprechend auch so in die cpp rein?

    System::Void Form1::openFileDialog1_FileOk(System::Object^  sender, System::ComponentModel::CancelEventArgs^  e) {Code}
    

    Danke euch!



  • Obige Frage hat sich erledigt, es funktioniert auf diese Art.

    Die nächste Frage ist:

    Ich kann ja an Form2 über dessen Konstruktur einen Pointer auf Form1 übergeben (mit (this)), womit ich innerhalb von Form2 auf Properties von Form1 zugreifen kann. Das klappte in meinem Versuch auch.
    Wie kann ich nun aber auf Elemente innerhalb von Form1 zugreifen, also z.B. auf den Text einer auf Form1 befindlichen Text-Box?

    Ich dachte, das müsste wohl so gehen, tuts aber nicht:

    pointer->textBox1->Text="hallo";
    

    Ich konnte aber durchaus alternativ den kompletten Pointer auf die TextBox selbst übergeben, und dann auf deren "Text" zugreifen.

    Gibt es eine Möglichkeit, anhand eines übergebenen Pointers herauszufinden, welche Objekte (hier die TextBox) auf diesem Objekt derzeit vorhanden sind, wie die heißen, und welche Pointer auf sie zeigen?

    Danke 🙂


Anmelden zum Antworten