const Char* geht nicht



  • Nur weil du einen wchar_t in einen "Char" umwandeln kannst, lässt sich das noch lange nicht auf Zeiger übertragen.

    Ansonsten: Was willst du mit dieser Klasse eigentlich erreichen? Du scheinst hier eher eine String-Klasse zu benötigen als diese sinnlose Wrapper-Klasse um Einzelzeichen.



  • Nene, das soll keine String Klasse werden, die habe ich schon. Ich möchte einfach mit meiner sinnlosen Char-Wrapper-Klasse auf ein wchar_t-Array zeigen und bin gerade etwas verwundert, dass das nicht geht. Ich wüsste jetzt auch nicht welchen Operator ich überladen könnte damit es funktioniert.
    Wenn ich diesen Kontruktor hinzufüge

    Char::Char(const wchar_t* value) :
    	value(*value)
    {
    }
    

    dann kann ich immerhin

    const Char* c = new Char(L"dfgdfg");
    

    schreiben. Auch wenn ich keine Ahnung habe mit was dann value initialisiert wird.



  • Du kannst mit einem Char-Zeiger nur auf Datentypen zeigen, die mit Char verwandt sind (d.h. abgeleitete Klassen) - da gehört wchar_t trotz der möglichen Typumwandlungen nicht dazu. Außerdem verpackt deine Klasse genau ein Zeichen und wird sich deshalb schwer tun mit einem kompletten Zeichen-Array.
    (bei deiner "Ersatzlösung" erzeugst du auf dem Heap ein Char, das unabhängig von der Zeichenkette ist - und initialisierst es mit dem ersten Buchstaben der Zeichenkette)



  • Streamer schrieb:

    Auch wenn ich keine Ahnung habe mit was dann value initialisiert wird.

    Aber Hauptsache mal etwas hingeschrieben, oder wie? 😉

    Deine Char -Klasse ist aber wirklich sinnlos. Genauso wie es sinnlos ist, zwei Konvertierungsoperatoren anzubieten oder eine Referenz auf const wchar als Konstruktorparameter zu nehmen. Und die Sinnlosigkeit geht mit der manuellen Speicheranforderung

    const Char* c = new Char(L"dfgdfg");
    

    weiter, wo du genauso gut

    const Char c(L'd');
    

    schreiben könntest, nachdem du den unnützen Zeiger in einen wchar_t umgeschrieben hast.



  • Nexus schrieb:

    Streamer schrieb:

    Auch wenn ich keine Ahnung habe mit was dann value initialisiert wird.

    Aber Hauptsache mal etwas hingeschrieben, oder wie? 😉

    Na, das hatte ich schon vermutet, dass er auf das erste Zeichen zeigen wird, alles andere hätte auch keinen Sinn gemacht.

    Nexus schrieb:

    Genauso wie es sinnlos ist, zwei Konvertierungsoperatoren anzubieten oder eine Referenz auf const wchar als Konstruktorparameter zu nehmen.

    Naja die Konvertierungsoperatoren brauche ich damit

    char c = Char(L'');
    

    funktioniert. Dass man diesen Operator zweimal anbietet (einmal mit und ohne const) habe ich so schon öfter im Internet gesehen.
    Zuletzt hier: www.cplusplus.com/reference/string/string/operator%5B%5D/
    Ok es war der []-Operator. Das mit der Referenz kommt daher dass ich davor noch "const Char& value" stehen hatte um den Copycontructor zu überschreiben, was aber eh unnötig gewesen wäre da dieser ja sowieso vom Compiler erstellt wird.

    Nexus schrieb:

    Und die Sinnlosigkeit geht mit der manuellen Speicheranforderung

    const Char* c = new Char(L"dfgdfg");
    

    weiter, wo du genauso gut

    const Char c(L'd');
    

    schreiben könntest, nachdem du den unnützen Zeiger in einen wchar_t umgeschrieben hast.

    Das ist aber nicht ganz das gleiche. Ich habe extra einen Zeiger gewählt, weil ich dann mittels c++ durch das Char Array "streamen" wollte, um so Zeichen für Zeichen auswerten zu können.



  • Streamer schrieb:

    Na, das hatte ich schon vermutet, dass er auf das erste Zeichen zeigen wird, alles andere hätte auch keinen Sinn gemacht.

    Dass wer auf das erste Zeichen zeigt? Innerhalb der Klasse hast du keinen Zeiger, nur ein wchar_t -Objekt. Du kannst also nur ein einzelnes Zeichen speichern und keine Zeichenkette.

    Streamer schrieb:

    Naja die Konvertierungsoperatoren brauche ich damit

    char c = Char(L'');
    

    funktioniert.

    Dass du diese Funktionalität brauchst, ist ein Hinweis darauf, dass du mit einem ganz normalen wchar_t besser beraten wärst. Was bringt dir die Klasse, wenn du keine Kapselung nutzt?

    Streamer schrieb:

    Dass man diesen Operator zweimal anbietet (einmal mit und ohne const) habe ich so schon öfter im Internet gesehen.

    Aber nicht so. Zwei Überladungen mit unterschiedlicher Const-Qualifizierung hat man nur dann, wenn eine Überladung das Objekt ändert. Du kopierst aber in beiden Funktionen den Member, änderst also nie das Objekt. Folglich reicht die const -Überladung. Wobei ich wie gesagt etwas fragwürdig finde, hier überhaupt einen Konvertierungsoperator anzubieten.

    Streamer schrieb:

    Das ist aber nicht ganz das gleiche. Ich habe extra einen Zeiger gewählt, weil ich dann mittels c++ durch das Char Array "streamen" wollte, um so Zeichen für Zeichen auswerten zu können.

    Wie schon gesagt: Du schaust dir momentan eh nur das erste Element des Arrays an, also kannst du auf den Zeiger geradeso gut verzichten.



  • Ok, jetzt hats glaube ich klick gemacht.
    Der

    Char(const wchar_t* value);
    

    Konstruktor hatte in der Klasse nichts zu suchen. Bei

    const Char* c = new Char(L"AAAAAA");
    

    erzeuge ich dynamisch außerdem noch einen Char während hier

    const wchar_t* c = L"AAAAAA";
    

    c nur ein Zeiger auf ein Array ist.

    Ich habe mal ein wenig rumgespielt

    wchar_t c1 = L'A';					//geht, logisch
    	wchar_t c2 = L"AAAAAA";				//geht nicht, logisch
    	wchar_t c3 = wchar_t(L"AAAAAA");	//geht, warum das?
    
    	wchar_t* c4 = L'A';					//geht nicht, logisch
    	wchar_t* c5 = L"AAAAAA";			//geht, logisch
    	wchar_t* c6 = wchar_t(L"AAAAAA");	//geht nicht, logisch
    
    	Char C1 = L'A';						//geht, logisch
    	Char C2 = L"AAAAAA";				//geht nicht, logisch
    	Char C3 = Char(L"AAAAAA");			//verdammt geht nicht
    
    	Char* C4 = L'A';					//geht nicht, logisch
    	Char* C5 = L"AAAAAA";				//verdammt geht nicht
    	Char* C6 = Char(L"AAAAAA");			//verdammt geht nicht
    

    und festgestellt, dass sich meine Char-Klasse in drei Punkten von der wchar_t Klasse unterscheidet. Gibt es eine Möglichkeit das sich meine Klasse genauso verhält?

    Was ist eigentlich dieses L"" ? Ist das eine "gecheatete" Kurzform für ein Array? Wie und wo wird L"" definiert. Kann ich evtl. ein Macro S"" definieren das es mir ermöglicht anstatt

    Char charArray[6] = {L'A', L'A', L'A', L'A', L'A', L'A'};
    	Char* c = charArray;
    

    folgendes schreiben zu können:

    Char* c = S"AAAAAA";
    

    analog zu

    const wchar_t* c = L"AAAAAA";
    


  • In Zeile 3 und 7 hast du einen Cast verwendet - damit sagst du dem Compiler, daß du klüger bist als er und er so tun soll, als ob der Wert tatsächlich ein wchar_t wäre - dabei kommt vermutlich nur Müll heraus, aber das ist ihm an der Stelle egal.

    Ansonsten ist L"..." ein Kürzel für wide-charakter String und bis jetzt kannst du da keine eigenen Kennzeichen definieren (keine Ahnung, ob es mit C++0x geht).



  • Das Problem ist wie ihr schon geschrieben habt, dass man einen "const wchar_t*"-Zeiger nicht in einen "const Char*" umwandeln kann. Obwohl würde das überladen des *-Operators dies evtl. ermöglichen?
    Das praktischste wäre natürlich, wenn dies hier gehen würde.

    const Char* c = S"AAAAAA";
    

    Dann bräuchte ich keine Zeiger umwandeln und die Konvertierungsoperatoren könnte ich mir auch schenken.



  • Mit C++0x sollte sowas möglich sein. Aber mir erschließt sich nicht, wozu das gut sein soll.



  • Meine Char-Klasse soll eben noch mehr können/anbieten als die wchar_t-Klasse, unter anderem soll sie z.B. von einer allen Klassen gemeinsamen Basisklasse abgeleitet sein.

    314159265358979 schrieb:

    Mit C++0x sollte sowas möglich sein. Aber mir erschließt sich nicht, wozu das gut sein soll.

    Wie genau?



  • Dir ist bewusst, dass wchar_t ein eingebauter Typ und keine Klasse ist?
    Du kannst in C++0x solche speziellen Literale erzeugen, aber dein const Char* wird nicht möglich sein.

    Ich wette es gibt einen schönen Weg, in Standard-C++ genau das zu erreichen, was du möchtest. Erkläre doch mal, was du vor hast.



  • Streamer schrieb:

    Das Problem ist wie ihr schon geschrieben habt, dass man einen "const wchar_t*"-Zeiger nicht in einen "const Char*" umwandeln kann. Obwohl würde das überladen des *-Operators dies evtl. ermöglichen?

    const Char* c = S"AAAAAA";
    

    Nein, zumal hier gar nirgends der operator* eingesetzt wird. Das Sternchen steht für Zeiger-Deklaration, nicht für Dereferenzierung.

    Streamer schrieb:

    Meine Char-Klasse soll eben noch mehr können/anbieten als die wchar_t-Klasse, unter anderem soll sie z.B. von einer allen Klassen gemeinsamen Basisklasse abgeleitet sein.

    wchar_t ist keine Klasse, sondern ein skalarer Datentyp.

    Was genau soll deine Klasse tun und wieso sollte sie von einer Basisklasse erben?


  • Mod

    Wenn es nur darum geht, für bestimmte Algorithmen das Literal wie ein Char-Array zu behandeln, könnte ein geeigneter Iterator(-adapter) helfen. Selbstdefinierte Literal werden meines Wissens bisher weder von Visual C++ noch von g++ unterstützt.



  • Ich lese aus XML-Dateien Resources ein. Das sind jede Menge unterschiedliche Klassentypen an die 100 Stück. Zusätzlich muss die Lib von Endanwendern noch an Klassentypen erweiterbar sein. Diese kommen Aufgrund der puren Vielzahl an unterschiedlichen Klassen alle in einen Vector der Zeiger vom Typ Base (der allen Klassen gemeinsamen Basisklasse) hält. Jetzt soll es natürlich auch Strings, Doubles, Ints, ... und eben auch Chars als Resourcen geben. Das geht aber nur wenn auch sie alle von der gleichen Basis abgeleitet sind. Darum die Wrapper-Klassen. Im Moment ist meine String-Klasse noch ein Wrapper um wchar_t. Es ist aber nur konsequent hier nun meine eigene Char-Klasse zu nehmen.
    Und jetzt kommt mir bitte nicht mit das kann man auch mit normalen C++-Mitteln machen oder du benutzt die falsche Programmiersprache. Natürlich kann man das mit den normalen C++-Mitteln auch schaffen, aber ich möchte in disem Leben nochmal mit dem Programm fertig werden. Ich warte ja nur darauf, dass jetzt noch die Leute aus dem Assembler-Forum kommen und mir raten, dass kann man das mit Assembler-Mitteln sogar noch eleganter als mit C++ erledigen kann ;). Natürlich kann man das. Ist halt alles eine Frage des Codeumfangs bzw. der Zeit.



  • Dann willst du keine char Klasse sondern eine String Klasse.

    Und alle Probleme sind gelöst.



  • Vielleicht ist das ein Anwendungsfall von boost::any.



  • Streamer schrieb:

    Ist halt alles eine Frage des Codeumfangs bzw. der Zeit.

    Und genau aus diesem Grund solltest du auch Code wiederverwenden. In deinem Fall die String-Klasse std::wstring . Du kannst ja immer noch eine Klasse darum herumkapseln, die von der gemeinsamen Basis erbt. Aber die gesamte Zeichenkettenfunktionalität auf der Grundlage von wchar_t* neu zu implementieren... Naja.

    314159265358979 schrieb:

    Vielleicht ist das ein Anwendungsfall von boost::any.

    Kaum.



  • Nexus schrieb:

    Kaum.

    Gut, dann halt nicht. ^^
    Ich habe boost::any noch nie gebraucht, war nur mal geraten. 😃



  • @314159265358979
    Das hatte ich auch schonmal durchgespielt finde die derzeitige Lösung allerdings nach anfänglicher Skepsis wegen den Wrapper-Klassen um die skalaren Datentypen ziemlich gut.

    @Shade Of Mine
    Im Prinzip hast du recht. Mich wurmt aber, dass dieses blöde

    const Char* c = L"AAAAAA";
    

    nicht geht.

    Char charArray[6] = {L'A', L'A', L'A', L'A', L'A', L'A'};
    Char* c = charArray;
    

    ist ja nun wirklich niemanden zuzumuten. Ich selber brauche das auch gar nicht, da ich in der Lib selber nur mit Strings arbeite. Aber vielleicht will ein Anwender die Char-Klasse mal so verwenden. Ein anderes Problem ist die Schnittstelle zur Win32-API wo ja noch viel mit const char* gearbeitet wird. Aber gut da könnte ich dann wie du schon gesagt hast mit meiner String Klasse eben eine entsprechende Umwandlung von String nach const char* anbieten.
    Allerdings hat Nexus ja die Kapselung angemahnt. D.h. innerhalb meiner String-Klasse, die ein Wrapper um die Char-Klasse darstellt, hätte ich ja dann gar keinen Zugriff mehr auf den wchar_t* Member der Char-Klasse. Eine Rückgabe dessen durch die String-Klasse wäre so nicht mehr möglich, oder doch? Alles ziemlich verwirrend.


Anmelden zum Antworten