Fehler bei CString-Rückgabe
-
Hallo,
ich habe die Klasse CPPString von CString geerbt und will sie jetzt um die Methode FromPos erweitern, die mir den rechten Teilstring ab Position xxx zurückgibt (ähnlich wie CString::Right, nur das von links gezählt wird)Implementierung:
CPPString CPPString::FromPos(int iPos) { return (*this).Left( (*this).GetLength()-iPos ); }Meine Klasse sieht so aus:
class CPPString : public CString { private: char* m_strString; public: CPPString(void); CPPString(const char* strString); ~CPPString(void); int ParseInt(void); long ParseLong(void); double ParseDouble(void); char* GetCharArray(void); void ToCharArray(char* strCharArray, size_t Size); CPPString FromPos(int iPos); // das funktioniert nicht };Ich bekomme folgenden Fehler:
Error 2 error C2664: 'CPPString::CPPString(const char *)' : cannot convert parameter 1 from 'ATL::CStringT<BaseType,StringTraits>' to 'const char *' c:\projects\cppstring test2\cppstring test2\cppstring.cpp 94
Ich verstehe diesen Fehler nicht.
Wo habe ich denn einen const char * deklariert/ übergeben?Meine Klasse CPPString ist doch zu CString kompatibel.
Ich möchte schon den String direkt zuweisen (so wie es auch Left und Right() macht) und nicht den Umweg über Pointer gehen.
Was ist falsch?
Besten Dank.
-
dlgig schrieb:
Ich verstehe diesen Fehler nicht.
Wo habe ich denn einen const char * deklariert/ übergeben?Hier:
CPPString(const char* strString);dlgig schrieb:
Meine Klasse CPPString ist doch zu CString kompatibel.
Das weiss ich nicht, da ich
CStringnicht kenne. Hier befindest du dich im Unterforum für Standard-C++ und die KlasseCStringgehört eindeutig nicht dazu. Diese ist doch Teil der MFC, oder?Wie sieht denn dein Konstruktor aus, was bietet die Basisklasse für Konstruktoren?
-
CString::Left(....) gibt nen CString zurück, keinen CPPString.
Deine Klasse braucht nen Konstruktor mit so ner Signatur:
CPPString(CString);
-
Moi schrieb:
CString::Left(....) gibt nen CString zurück, keinen CPPString.
Deine Klasse braucht nen Konstruktor mit so ner Signatur:
CPPString(CString);Ich verstehe nciht ganz was du meinst?
---
Stimmt... CString scheint zur MFC zu gehören.
Nexus schrieb:
Wie sieht denn dein Konstruktor aus, was bietet die Basisklasse für Konstruktoren?
Mein Kunstruktor:
CPPString::CPPString(const char* strString):CString(strString) { m_strString = (char*)calloc(0,sizeof(char)); }ich benutze eigenltich nur folgenden CString Konstruktor:
CStringT ( const char String );
-
dlgig schrieb:
Ich verstehe nciht ganz was du meinst?
Wenn das stimmt, hast du einen Fehler in
CPPString CPPString::FromPos(int): Du hast RückgabetypCPPString, gibst aber einenCStringzurück.
-
Nexus schrieb:
dlgig schrieb:
Ich verstehe nciht ganz was du meinst?
Wenn das stimmt, hast du einen Fehler in
CPPString CPPString::FromPos(int): Du hast RückgabetypCPPString, gibst aber einenCStringzurück.Habe jetzt den Rückgabewert auf CString geändert. Jetzt gehts.
ABER ich dachte, dass voneinander abgeleitete Klassen zueinnader Kompatibel sind.Kann ich nicht CAbgeleitet CBasisKlasse zuweisen?
CAbgeleitet = CBasisKlasse;
CBasisKlasse = CAbgeleitet;
??
-
Wenn du einen CString zurückwirfst mittels return, in der Signatur aber ein CPPString steht, dann wird versucht den CString in einen CPPString zu konvertieren. Und dafür brauchst Du nen Konstruktur mit der Signatur wie oben angesprochen.
Der ganze Laufzeitpolymorphiekram funzt nur mit Pointern. Du müsstest nen CPPString * zurückwerfen, damit es kompiliert, aber dann wird es kompliziert, weil du dann die ganze Speicherverwaltung manuell implementieren musst.
-
dlgig schrieb:
Habe jetzt den Rückgabewert auf CString geändert. Jetzt gehts.
ABER ich dachte, dass voneinander abgeleitete Klassen zueinnader Kompatibel sind.Nein, nicht zueinander. Ein
Derivedist sicher einBaseund kann als solches angesehen werden (sofernpublic-Vererbung eingesetzt wurde). Umgekehrt ist einBase-Objekt keinDerived.Moi schrieb:
Der ganze Laufzeitpolymorphiekram funzt nur mit Pointern.
Mit Referenzen geht es auch. Hier muss man vorsichtig sein: Verweise (Zeiger/Referenzen) auf abgeleitete Klassen können implizit als solche auf Basisklassen angesehen werden. In umgekehrter Richtung muss man entweder
dynamic_casteinsetzen, um eine Laufzeitprüfung zu erhalten, oderstatic_cast, das aber bei fehlerhaftem Downcast undefiniertes Verhalten hervorruft.
-
Danke.
Jetzt gehts auch so.Habe jetzt wie Moi gesagt, den fehlenden Konstruktor hinzugefügt
CPPString::CPPString(CString csString):CString(csString) // Notwendig für Typcasting: CString To CPPString { m_strString = (char*)calloc(0,sizeof(char)); }Denke ich habe auch den Grund verstanden:
Immer wenn ein TypeCast notwendig ist: Basisklasse in AbgeleiteteKlasse
dann ist ein Konstruktor erforderlich, denn
bei jedem TypeCast wird der Konstruktor aufgerufen.Richtig?
-
m_strString = (char*)calloc(0,sizeof(char));das sieht extrem falsch aus...
-
Hm... naja.
Ich würde lieber dendynamic_castbevorzugen, denn genau dafür ist er da.> bei jedem TypeCast wird der Konstruktor aufgerufen.
Kann man nicht allgemein sagen. Der Compiler sucht verschiedene Möglichkeiten, wie er casten kann. Irgendwann kommt er auf die Konstruktoren. Wenn das Objekt, das gecastet werden soll, als Parameter im Konstruktor vorhanden ist, wird der Compiler versuchen, diesen Konstruktor zu benutzen.
class HoldsAnInt { private: int data; public: HoldsAnInt(int d) : data(d) { } }; void f(HoldsAnInt hai); [ ... ] f(23); // == f(HoldsAnInt(23)) (Funktionsartiger Cast) == f(static_cast<HoldsAnInt>(23))Das kann man natürlich auch mit abgeleiteten Klassen, dynamischer Polymorphie und Heap-Objekten machen machen. Entweder macht der Compiler die Arbeit des Castens zu seiner Zeit (per explizitem Konstruktor) oder das Programm selbst zur Laufzeit (mit Offsets).
-
Hat eigtl schon mal jmd gesagt, dass man das, was du dort machst, nicht machen sollte?

Was spricht gegen eine freie Funktion?
Den Aufbau deiner Klasse versteh ich eh nicht ganz... wofür nochmal der pointer? cstring hält doch den string an sich schon!?
-
unskilled schrieb:
m_strString = (char*)calloc(0,sizeof(char));das sieht extrem falsch aus...
Warum das? Ich allokiere erstmal 0 Byte Speicher.
Später wird er dynamisch mit realloc angepasst.
Ich allokier gleich am anfang irgendwas, damit ich später nicht mehr unterscheiden muss, ob der zeiger noch null ist oder schon auf speicher verweist.
-

-
unskilled schrieb:
Hat eigtl schon mal jmd gesagt, dass man das, was du dort machst, nicht machen sollte?

Bin mir nicht ganz sicher, ob du mich meints.
[quote]Was spricht gegen eine freie Funktion?
Den Aufbau deiner Klasse versteh ich eh nicht ganz... wofür nochmal der pointer? cstring hält doch den string an sich schon!?Ich wollte eine Funktion integrieren, die mir den CString als Char-Array ausgibt.
Manchmal ist man ja auf char* angewiesen z.B. wenn man mal sprintf, fopen, _popen().
Da die guten alten C-Funktion manchmal doch besser zu handeln sind oder man ein Char-Array viel besser durchparsen kann.@Ad aCTa
Verstehe dein Beispiel nicht ganz. Was macht der Code?
-
Ich wollte eine Funktion integrieren, die mir den CString als Char-Array ausgibt.
Gibts schon: GetBuffer()
http://msdn.microsoft.com/en-us/library/5bzxfsea.aspx
Simon
-
[quote="theta"]
Gibts schon: GetBuffer()
http://msdn.microsoft.com/en-us/library/5bzxfsea.aspx
SimonGeht leider nicht bei Unicode-Unterstützung. Also wenn dort der Haken gesetzt für Unicode-Libories gesetzt ist, gehts damit nicht mehr - bekomme so nur das 1. Zeichen.
Deswegen mache ich das so:
char* CPPString::GetCharArray(void) { int iLenght = (*this).GetLength(); m_strString = (char*)realloc( m_strString, sizeof(char)*(iLenght+1) ); int i = 0; for ( i=0; i<iLenght; i++ ) { m_strString[i] = (char)(((LPCTSTR)(*this))[i]); } m_strString[i] = '\0'; return m_strString; }
-

-
Geht leider nicht bei Unicode-Unterstützung.
Das würd ich bezweifeln wollen... was heißt denn geht nicht? minimalbsp?
(am besten so was, wie#include <iostream> #include <CString> //richtig? int main() { CString test = L"asd"; std::wcout << test.GetBuffer() << std::endl; }. ich hab nur kein von der cli(?)-bibliothek - aber ich denke ja, du castest irgendwo nach char* und das war der fehler...)
sry, aber das was du hier machst, ist alles iwie total falsch und hässlich und noch viel mehr... du solltest dich noch ein wenig belesen, bevor du das nächste mal so etwas versuchst ;o)
ich würde solche fkt auch prinzipiell als freie fkt. implementieren, fänd ich auch viel zweckmäßiger...
thetas quellcode hatte nur am rande was mit deinem problem zu tun ;o) sein quelltext hat in so fern keinen bezug zu deinem eigentlichen problem (da gings um dynamic_cast und dessen funktionsweise)
bb
-
ich hab nur kein von der cli(?)-bibliothek
ehm, was mit cli? CString kommt aus der MFC / ATL, reines C++, ausgeschmückt mit unmengen von Makros...
Oder hab ich was verpasst?Simon