2 Stimmen

der richtige Weg, um neue Instanzen aus einer Unterklasse von C++ string zurückzugeben

Ich möchte die C++-String-Klasse zu erweitern, die Rückgabe von Unterklasse Referenzen (anstelle von übergeordneten String-Referenz), aber dieser Code-Auszug...

#include <string>
using namespace std;

class mystring : public string
{
public:
 mystring&  left( int cnt )
 {   return  (mystring&)mystring( substr(0,cnt) );
 }
};

erzeugt diesen VS8-Compilerfehler:

Fehler C2440: '' : kann nicht konvertieren von 'std::basic_string<_Elem,_Traits,_Ax>' nach 'mystring'

Was ist der richtige Weg, mystring::left() zu deklarieren, so dass der Compiler aufhört, sich zu beschweren, hoffentlich auch die Besetzung zu beseitigen?

6voto

dirkgently Punkte 104289

Fehler C2440: '' : kann nicht von 'std::basic_string<_Elem,_Traits,_Ax>' nach 'mystring' konvertieren

Von der MSDN-Seite über C2440:

C2440 kann auch auftreten, wenn eine falsche Verwendung einer benutzerdefinierten Konvertierung auftreten. Für weitere Informationen über benutzerdefinierte Konvertierungen finden Sie unter Benutzerdefinierte Konvertierungen). Das folgende Beispiel erzeugt C2440.

Der Fehler, auf den Sie stoßen, liegt daran, dass Sie versuchen, ein Objekt der Basisklasse über einen Verweis auf ein Objekt der abgeleiteten Klasse zurückzugeben. Es funktioniert auch andersherum. Daher brauchen Sie den Cast - was schlecht ist.

Standardcontainer (einschließlich std::string ) nicht für die Vererbung geeignet sind, verwenden Sie stattdessen die Aggregation.

Sie brauchen die Besetzung nicht, um string& .

Versuchen Sie so etwas:

#include <string>
using namespace std;

class mystring     {
public:
 // create an appropriate conversion op/ctor between string -> mystring
 mystring(string const& s) : impl(s) {}
 mystring  left( int cnt )
 {   
     return mystring( impl.substr(0,cnt) );
 }
 string impl;

};

4voto

Nicolás Punkte 7313

Das Problem scheint zu sein, dass substr gibt eine std::string und nicht eine Instanz Ihrer Unterklasse. Haben Sie eine mystring::mystring(const std::string&) Konstrukteur?

Und warum zum Erde unterklassifizieren Sie std::string überhaupt? :D

Es ist wahrscheinlich besser, eine freie Funktion zu schreiben, anstatt eine Unterklasse zu bilden.

#include <string>

namespace mystring {
  std::string left(const std::string& str, int cnt)
  {   
     return str.substr(0,cnt);
  }
}

3voto

Seien Sie vorsichtig, wenn Sie von einer Klasse aus dem Namensraum std ableiten.

siehe Permalink um auf meine eigene Frage von peterchen zu antworten.

EDIT Die Essenz des Artikels, auf den der Permalink verweist, ist: Sie können von std::string ableiten. Aber Sie sollten keine neue Mitgliedsvariable einführen.

1voto

Georg Fritzsche Punkte 95256

Der Compiler sagt Ihnen bereits, wo das Problem liegt - er kann nicht von std::string a mystring da Ihre Klasse nicht aus std::string .

Sie sollten die Typen der Standardbibliotheken jedoch nicht unterklassifizieren, dafür sind sie nicht geeignet - verwenden Sie Komposition.

Lassen wir diese Frage für einen Moment beiseite:
Sie müssen einen Konstruktor bereitstellen, der eine std::string . Aber das hinterlässt immer noch ein Problem: Sie geben einen Verweis auf eine temporäre zurück - geben Sie hier einfach den Wert zurück.

Ihre Klasse könnte nun wie folgt aussehen:

class mystring  
{
    std::string m_string;
public:
    mystring(const std::string& s) : m_string(s) {}

    mystring left(std::string::size_type cnt) {
        return m_string.substr(0,cnt);
    }
};

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X