Klasse in sich selber Initialisieren/Instanzieren alá System::String?



  • verdammt wenn das stimmt ist das echt mies, ist nen schöner luxus und da ich ehh nur nen bytearray habe das ich sogar nullterminieren lasse (brauche nur 215 von 256 zuständen) wäre das echt ideal, und leider ist ja system::string nicht vererbbar. Gibt es da keinen kniff über ach wer weis was.

    im endeffekt brauche ich ja nur die speicheraddresse meiner nicht initialisierten variable und die ohne parameterübergabe irgendwie in meine klasse zu drücken. muss da doch nen weg geben.



  • Ich versteh ehrlich gesagt immer noch nicht worauf du hinaus willst 🙄

    Du hast nen ByteArray das 215 Felder lang ist, oder meinst du, du willst ein Array von Bytes(jedes Byte kann bei dir Werte zwischen 0 und 215 annehmen) - sprich fast wie String, nur halt darf ein Zeichen nur bis 215 gehen?



  • nee deine erste annahme ist schon richtig will halt ne klasse bauen mit den eigenschaften von system::string also:

    MyClass ^m;

    m = Bytearray;

    nicht 215 felder größ ich brauche nur 215 zustände also sowas wie 0-215 bzw 1-216 damit kann mein array mit 0 terminiert werden, was eines string gleich kommt nur dfas es halt nicht als string gedacht ist, und da ich nicht von string ableiten darf würd ich das gern nachbauen. Ist halt nen geiler luxus.

    achaj ich weis warum ich gcnbew nicht brauche, weil halt die daten bei string konform sind wodurch die auto. initiallisierung der variable problemlos erfolgen kann. Ich will es halt nachbauen, das ist alles. Und da muss es doch nen weg geben, wäre doch doof wenn nicht. Zudem das der compiler das macht ist nur in einem fall möglich:

    System::String ^str ="x";

    aber bei

    System::String ^str;

    str = "x";

    kann der compiler nicht vorher die variable initialisieren weil er kann sich nicht sicher sein das es auch wirklich dazu kommt. Zb. str ist global und irgendwo lokal wird erst der wert zugewiesen und so auch die initialisierung das kann der compiler garnicht wissen, also steht ein anderer prozeess dahionter der auch wärend der laufzeit aktive ist, und dieser muss doch nutzbar sein.



  • achaj ich weis warum ich gcnbew nicht brauche, weil halt die daten bei string konform sind wodurch die auto. initiallisierung der variable problemlos erfolgen kann.

    hmm... ich hätte jetzt getippt das "string" nen keyword vom compiler is und das der Compiler es von alleine kapiert 😃

    probier doch ma

    String ^str = gcnew String(); //hab das blöde gefühl als hätte ich gcnew falsch geschrieben^^(MFC,C# only, sry)
    

    da haste dann dein gcnew



  • ich geb mir die kugel schreib ich den so mies^^? also nochmal ich will das verhalten von System::String bei der initialisierung nachbauen für eine eigene klasse. und nein der compiler kann es eben nicht immer wissen.

    Bsp1:
    [GLOBAL]
    char *str1;
    System::String *str2;

    [irgendwo im prog lokal]
    str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
    str2 = "huhu"; // alles in ordnung str2 wird automatisch initialisiert

    in diesem fall kann der compiler doch garnicht wissen ob wirklich str2 mit "huhu" initialisiert wird, oder ich steh total auf dem schlauch. Der Compiler weis es nur in diesem fall.

    Bsp2:

    [irgendwo im prog]
    char *str1 = "huhu"; //ok weil direkt initialisiert compiler kann sich zu 100% sicher sein
    System::String *str2 = "huhu"; // gleicher fall, hier besteht die 100%ige sicherheit

    und mich interessiert das verhalten von System::String aus dem Bsp1. Und wie man sieht kein gcnew, genau das interessiert mich. Hoffe das war nu verständlich^^.

    Edit:

    das da gcnew geht weis ich doch, ich will aber eben dahin eine klasse zu schreiben die daten konform eines string aufnimmt, ohne das ich sie vorher initialisieren muss.



  • Ich denke ma das dir da reflection weiterhelfen sollte, sicher bin ich mir aber net...
    setzt mal

    [ComVisible(true)]
    

    vor/über deine Klasse und

    [MethodImpl(MethodImplOptions.InternalCall)]
    

    vor/über deinen Constructor, wichtig dabei ist das der Constructor nur ein Parameter haben darf(wenn ich mich net irre) und der eine Parameter ein zeichen-array sein muss (in diesem falls sollte ein char-array das richtige sein)

    note:
    ComVisible liegt in System.Runtime.InteropServices
    MethodImpl liegt in System.Runtime.CompilerServices

    edit: ah und ma so btw...

    Bsp1:
    [GLOBAL]
    char *str1;
    System::String *str2;

    [irgendwo im prog lokal]
    str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
    str2 = "huhu"; // alles in ordnung str2 wird automatisch initialisiert

    also mir fallen iwie direkt erstma 4 fehler auf... nur schlimm ist der hier:

    str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
    

    les dir plz noma so ein paar grundsachen durch, gerade was speicher reservierung etc betrifft, auch wenn man es in .Net nich mehr so braucht.



  • hmm sieht interessant aus teste das gleich mal danke und was speicherverwaltung angeht brauche ich mir nichts durch zu lesen, habe schlieslich nen eigenen gc geschrieben als ich noch unmanaged geprogt habe, mir ist klar das da ein fehler ist habe ich ja auch dazu geschrieben es dient nur zum vergleich und zur veranschaulichung was ich meine mehr nicht^^. aber das mit internalcall klingt sehr interessant. Danke dir 🙂

    Edit:

    speziell das mit str1 sollte zeigen das da der compiler die definition nicht übernimmt weil er es garnicht übernehmen kann, denn woher soll er sich sicher sein das diese initialisierung auch wirklich statt findet. Im gegensatz dazu System::String da weis es der compiler auch nicht dennoch ist das kein problem also steht da ein prozess wärend der laufzeit dahinter und nicht der compiler. Nur dazu dient Bsp1. (siehe oben wegen aussage das compiler initialisierung übernimmt). Im gegenzug Bsp2, wo der compiler wirklich die initialisierung übernhemen kann weil es fest steht das der wert wirklich zugewiesen wird sobald es zur variable definition kommt.



  • eigenen gc? klingt interessant... öffentlich? link ? 😃



  • nö öhhm wieso auch das ist recht einfach, das sind nur 2 doppelt verkettete listen die über ein interface gefüllt werden sobald ein type initialisiert wird. achja vergessen zu sagen habe es mir da einfach gemacht und von allen standarttypen eigene typen gebaut die sich am interface bedienen also mit den standarttypen von c++ geht mein gc nicht. ist evtl möglich aber echt kein elan das zu schreiben^^. hatte da also meinStrin meinInt mein ....... die erste liste beinhalten pointer auf die variablen (instanzen) die zweite die addressen der instanzen selbst. nun ist damit die erste liste in der lage die aktuellen werte der variablen zu erkennen wärend die 2. liste alle bis dahin aufgetauchten addressen der instanzen/objekte speichert. dann nur noch vergleichen der 1. und 2. liste und addressen die in der 2. liste gefunden werden aber nicht in der ersten werden gelöscht denn diese objekte haben keinen bezug mehr zum programm und liegen einfach nur im speicher ohne das zugriff darauf genommen werden könnte (ausser der 2. liste die ne art history ist der erstellten instanzen). wie gesagt sehr einfach gehalten, aber läuft 1a und ohne leaks. Aber so existiert der gc auch nicht mehr, er iust mittlerweile umgebaut und in ein eigenes datenbanksystem eingebunden. Und an der arbeite ich gerade diese DB hat eine art universaltyp in dem jeder typ (auch in arrayform also array<> und vector<> unterstützung) gespeichert werden kann und auch wieder ausgelesen werden kann von managed sowie unmanaged code. nur ist das doch nen hartes brot. weil arbeite auch an einer funtion die mir jeden datentyp zurück liefert also nicht eine funktion für jeden typ sondern eine für alle und diese soll für managed sowie unmanaged funktionieren. wenn ich damit fertig bin stell ich es gern mal hier rein.

    Edit:

    auch hier erstelle ich wieder meine eigenen typen die über interfaces an den gc und die db gehen. in dem sinne mache ich es mir wieder einfach. doch das schönste dabei im managed wird fast zu 100% der normale gc umgangen, weil finde den assi nach nem test bei dem ich 1000000 string erstellt habe und wieder gelöscht hatte das prog am ende nen leak von 2,5 MB mein gc dagegen hat nach dem gleichen test nen leak von 0 MB^^



  • aso...
    zurück zum thema, da das was ich gepostet habe denk ich mal nicht funktionieren wird, und du dann noma nachfragen wirst, hier schonma die antwort

    Keywords are predefined reserved identifiers that have special meanings to the compiler. They cannot be used as identifiers in your program unless they include @ as a prefix. For example, @if is a legal identifier but if is not because it is a keyword.

    also das gleich was schonma gesagt wurde.... geht net



  • Hallo Oelnsi,

    jetzt versuche ich die Runde auch noch etwas durcheinander zubringen.
    In erster Line kannst Du den String nicht ohne den Dach (^) in C++/CLI verwenden.

    Der String^ landet grundsätzlich auf dem verwalteten Heap.
    Aus technischer Sicht handelt es sich beim Datentypen String um eine Sonderform eines Arrays, die weitgehend vom Compiler verwaltet wird.
    Da das Dach(^) und gc in gcnew für Garbage Collected (Müllhalte) steht.
    Das heißt im Einzelnen, dass der GC wird von Zeit zu Zeit ausgelöst.
    Zeiger, Pointer, Handels usw. die mit gcnew vereinbart wurden, aber kein zugriff mehr erfolgt, da die Methode schon verlassen wurde, werden aus dem Speicher entfernt.
    Dadurch sollen keine "Leichen" mehr im Speicher liegen.
    Nun noch weinig zum Thema Destruktoren un Finalisierer.
    Dann kommt ein wenig Code…
    Die Destruktoren "~Form1()" und Finalisierer "!Form1()" sind das Gegenstück zum Konstruktor.
    Sie werden bei der Zerstörung einer Instanz aufgerufen.
    Ein Destruktor wird ausgeführt, wenn eine Instanz „per Hand“ zerstört wird, z.B. durch delete.
    Der Finalisierer dagegen wird ausgeführt, wenn der Speicher durch die Garbage Collection aufgeräumt wird.
    Wobei Speicherlücken entstehen können.

    Solltest Du zum Beispiel delete vari1; ausführen, wird vari1 freigeben und bei der nächsten Ausführung vom GC gelöscht und somit wieder Speicher freigegeben.

    public:
    
    String^ vari1;
    String^ vari2;
    
    private: System::Windows::Forms::Button^  button1;
    public: 
    
    	Form1(void)
    	{
    		InitializeComponent();
    		//
    		//TODO: Konstruktorcode hier hinzufügen.
    		//
    		vari1 = nullptr;
    		vari2 = nullptr;	
    	}
    
    //Button Click...
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
    			 {
    				vari1 = "vari1";
    				vari2 = "vari2";
    
    				MessageBox::Show(vari1,vari2);
    
    			 }
    

    Jetzt kommt noch ein ganz fieses Beispiel.
    Leg mal eine normale Konsole an, lösch bitte den kompletten Code aus der *.cpp und füge den nachstehenden Code ein und führe das Programm über Strg+F5 aus.

    // Destrukter und Finalisierer.cpp: Hauptprojektdatei.
    
    /*#################################################################
    
    Destruktor und Finalisierer
    
    ##################################################################*/
    
    #include "stdafx.h"
    
    using namespace System;
    
    //die Klasse sherry
    
    ref class sherry
    {
    	Int32 alter;
    
    	Int32 liter;
    
    public:
    
    	//der Konstruktor
    
    	sherry(Int32, Int32);
    
    	//der Destruktor
    
    	~sherry();
    
    	//der Finalisierer
    
    	!sherry();
    
    	void ansehen();
    };
    
    //die Methode für den Konstruktor
    
    sherry::sherry(Int32 tAlter, Int32 tLiter)
    {
    	alter = tAlter;
    
    	liter = tLiter;
    }
    
    //die Methode für den Destruktor
    
    sherry::~sherry()
    {
    	//bitte in einer Zeile eingeben
    
    	Console::WriteLine("Der Destruktor für den {0} Jahre alten Sherry wurde aufgerufen.",alter);
    }
    
    //die Methode für den Finalisierer
    
    sherry::!sherry()
    {
    	//bitte in einer Zeile eingeben
    
    	Console::WriteLine("Der Finalisierer für den {0} Jahre alten Sherry wurde aufgerufen.",alter);
    }
    
    void sherry::ansehen()
    {
    	//bitte jeweils in einer Zeile eingeben
    
    	Console::WriteLine("Der Sherry ist {0} Jahr(e) alt.",alter);
    
    	Console::WriteLine("Die Flasche enthält {0} Liter.",liter);
    }
    
    //eine Funktion mit einer lokalen Instanz, die nicht auf dem verwlteten Heap liegt
    
    void lokaleInstanz()
    {
    	sherry flasche4(4,10);
    
    }
    
    int main(array<System::String ^> ^args)
    {
        //Instanzen auf dem verwalteten Heap erzeugen
    
    	sherry^ flasche1 = gcnew sherry(1,1);
    
    	sherry^ flasche2 = gcnew sherry(2,1);
    
    	sherry^ flasche3 = gcnew sherry(3,1);
    
    	//eine lokale Instanz erzeugen
    
    	lokaleInstanz();
    
    	//Attribute anzeigen
    
    	flasche3->ansehen();
    
    	//Instanz flasche1 per Hand "zerstören"
    
    	delete flasche1;
    
        return 0;
    }
    

    Hoffe es kommt ein wenig Licht ins Dunkle...

    Gruß, Doug_HH



  • verdammt das will ich nicht so hinnehmen, das ist doch mist, naja und wenn ich mit asm alles komplett zerlege ich schaffe das. denn eines ist klar der compiler kann nur vorbereitungen treffen das es dann im prog initiallisert werden kann, aber selber macht er es nicht. Denn es geht ja nicht nur mit const char usw. sondern auch mit variablen wodurch der compiler nichmal wissen kann was für eine länge der string hat sondern erst zur laufzeit feststellbar ist. das heisst wo meine stringvariable steht fügt er was spezielles ein was er bei anderen klassen nicht einfügt, anders geht es ja garnicht. und dort will ich ran, bzw wissen was er da genau einfügt. Trotzdem danke für eure Hilfe 🙂



  • das ist zwar schön und nett aber ?? ich meine ich weis wie ich lösche und der gleichen dennoch hat der gc leaks, zudem bestrifft das nichtmal mein problem. Dennoch schönes Bsp. 🙂 Danke



  • @Doug_HH:
    die xte unnötige Hilfe...

    @oelsni:
    solangsam geb ich es auf xD
    Wir verstehen schon was du willst.... schon beim 2ten post^^ aber die Antwort ist immer gleich. Der compiler macht das von sich selber aus(jo, asm is ne möglichkeit... aber ob sich DER aufwand sich dafür lohnt?? und irgendwann kommtn update und is wida alles futsch xD)

    nur noma so btw (brauchst auf diesen abschnitt nix zu posten^^, schreibe es ma kurz in C#):

    string foo = "bar";
    

    ist equivalent zu

    char[] chars = new char[]{'b','a','r'};
    String foo = new String(chars);
    

    thema für mich closed //evtl noch offtopic 😃



  • nee ist auch alles geklärt kann mir vorstellen was der compiler da in etwa macht. und mir egal ich will den LUXUS^^

    ich meine es geht ja auch so aber bin halt nen druff mehr gibt es da nicht zu sagen *g Ich drück die scheise mit asm durch ist zwar eine sehr unschöne methode aber am ende sieht es so aus wie bei System::string freu mich schon auf die arbeit juhuu:p

    P.S.: wenn ich eine edle methode finde das zu realisieren stell ich dir hier rein damit euch die kinnlade einschläft 😮

    bis dahin nix mehr hier schrieben ausser ihr habt bock drauf für mich ist die sache geklärt.


Anmelden zum Antworten