2009-04-25 16 views
0

Ich versuche, eine antike C++ - Code-Basis von gcc 3.2 auf gcc 4.1 zu verschieben, da ich ein paar Probleme habe. Von all den Problemen bleibt mir Folgendes ahnungslos (ich denke ich habe zu viel Zeit mit Java verbracht oder ich habe die Grundlagen von C++ vergessen :-P).C++ Operator Überladung Auflösung Ambiguität

Ich habe eine Template-Klasse

template < class T > class XVector <T> 
{ 
    ... 
    template < class T > T 
    XVector <T>::getIncrement() 
    { 
     ... 
    } 
    template < class T > int 
    XVector <T>::getValue (size_t index, T& value) 
    { 
     ... 
     //The problematic line 
     value = (T) (first_value + getIncrement()) 
        * (long) (index - first_index); 
     .... 
    } 
} 

Diese Klasse auf der STL std basiert :: vector. Ich habe eine zweite Klasse TypeValue und seine wie folgt definiert, die eine der int, long und ihre vorzeichenlosen Varianten float, double, std :: string enthalten können. Überlastet auch fast alle möglichen Betreiber.

class TypeValue 
{ 
    union 
    { 
     long* _int_value; 
     double* _real_value; 
     string* _text_value; 
    } _value; 

    TypeValue(); 
    explicit TypeValue(long _long); 
    explicit TypeValue(int _int); 
    explicit TypeValue(unsigned long _ulong); 
    ... 
    //similarly for all the remaining supported types. 
    TypeValue(const TypeValue&) //Copy constructor 

    virtual TypeValue& operator=(const TypeValue &rhs); 
    TypeValue& operator+ (TypeValue&)const; 
    TypeValue& operator* (TypeValue&)const; 
    ... 
    //For all the basic operators 

    operator long() const; 
    operator int() const; 
    operator unsigned long() const; 
    operator unsigned int() const; 
    ... 

} 

Und schließlich ich eine andere Klasse, nennen wir es die build_breaker, die ein Objekt als XVector <TypeValue> a_variable; schafft. Wenn ich das nun auf gcc 3.2 kompiliere, kompiliert das ohne Probleme. Aber wenn ich versuche, diese auf gcc kompilieren 4.1 bekomme ich Fehler mehrdeutig Überlastung für operator* in der Klasse XVector sagen, und die Kandidaten

 
operator*(long int, long int) 
operator*(int, long int) 
operator*(long unsigned int, long int) 
operator*(unsigned int, long int) 
operator*(double, long int) 
operator*(float, long int) 

wird, wenn der Compiler sagte, es hatte Probleme ein Spiel für T zu finden * lang, das hätte hat Sinn gemacht, aber warum versucht es, es in den nativen Typ zu schreiben und dann die arithmetische Operation durchzuführen? Bitte helfen Sie mir dabei.

Vielen Dank im Voraus.

+0

Ihre arithmetischen Operatoren sollten const-Referenzen akzeptieren und zurückgeben, da sie const-Funktionen sind. Ihr Zuweisungsoperator sollte eine const-Referenz akzeptieren, aber die Methode selbst ist nicht sehr sinnvoll. Es ist ein Zuweisungsoperator, also sollte er das ändern, von dem Sie ihn nennen. –

+0

Geringfügige Korrektur, der Zuweisungsoperator wird als

 virtual TypeValue& operator=(const SdmsTypedValue &rhs); 
deklariert. Es ist kein reines virtuelles, sondern hat eine Methodendefinition. – cx0der

+0

Nicht "korrigieren" Sie es in den Kommentaren. Korrigiere es richtig, indem du deine Frage redest und richtig machst. Und wenn Sie das tun, denken Sie bitte auch daran, dass wir "SdmsTypedValue" noch nie zuvor gesehen haben. Dies ist der erste, den du diesen Typ erwähnt hast. –

Antwort

4

Der zweite Operandentyp ist long [int]. Die erste ist TypeValue, ich erwarte, aber es gibt keinen Operator *, der diese beiden genauen Typen nimmt. Es gibt jedoch viele andere Typkombinationen für diesen Operator, die der Compiler durch eine implizite Konvertierung für den ersten Operanden auswählen kann. Die Sprache erlaubt dem Compiler dies zu tun, um zu versuchen, eine Übereinstimmung zu finden.

Aber welche der vielen Konvertierungen sollte es wählen? Der Compiler hat keine Möglichkeit zu wählen, ob int besser ist als long int. (Sie könnten argumentieren, dass, da der zweite Operand long int ist, sollte dies das bevorzugte Konvertierungsziel sein, aber das ist nicht die Art und Weise funktioniert.)

Also, ein Tipp: Erstens, nicht so viele implizite Konvertierungen liefern. Da die Klasse nur long, double und string enthalten kann, sind dies die einzigen drei Konvertierungen, die ich bereitstellen würde. Das allein wird wahrscheinlich Ihr Problem nicht lösen, aber es kann die Größe der Fehlerausgabe verringern und andere Dinge besser handhabbar machen.

Statt (index - first_index) der Umwandlung long zu geben, sollte deren Umwandlung T (das heißt, TypeValue) statt zu geben, denn das scheint der Betrieb zu sein, das Sie wirklich an erster Stelle ausführen wollten.

+0

Hallo Rob, Wenn ich den Operator * als TypeValue & Operator * (const lang &) überladen, gab mir der Compiler Fehler: ISO C++ sagt, dass diese mehrdeutig sind, obwohl die schlechteste Konvertierung für die erste besser als die schlechteste ist Umwandlung für das zweite: Kandidat 1: TypeValue TypeValue :: operator * (const long int &) Kandidat 2: operator * (float, size_t) cx0der

+0

ich nicht raten, eine TypeValue lange Überlastung für Betreiber * Bereitstellung, habe ich ? Bieten Sie kleinere Konvertierungen und geringere Überlastungen an. Der einzige Operator, den Sie angeben sollten, ist dies: << TypeValue-Operator * (TypeValue const &) const; >> Es ist eine const-Methode, die eine const-Referenz akzeptiert und einen Wert zurückgibt. (Geben Sie keine Referenz zurück.) Dann, wie ich bereits sagte, type-cast (index - first_index) als Typ T, an welchem ​​Punkt der Compiler ein TypeValue-Objekt aus dieser Differenz konstruiert und mit dem ersten TypeValue-Objekt multipliziert du hast. –

0

Wir müssten wissen, was T ist. Es sieht so aus, als ob Sie einen XVector mit einem Typ (wie unsigned char zum Beispiel), der in alle diese Typen umgewandelt werden kann, und der Compiler weiß es nicht welches man wählen sollte.

+0

T ist TypWert. – xtofl

+0

In diesem Fall ist es ziemlich klar. Es gibt viele implizite Konvertierungen von TypeValue, und der Compiler weiß nicht, welcher zu wählen ist. In der Tat, ich verstehe nicht, wie das jemals unter gcc 3.2 – Gorpik

+0

kompilieren könnte Dieser Code kompiliert ohne Fehler oder Warnungen in gcc 3.2.3, die mich immer noch amüsiert! – cx0der

2

Ich würde alle Konvertierungs Betreiber benannten Funktionen ändern, so dass:

operator long() const; 

wird

long ToLong() const; 

Implizite conversiopns über Cast-Operatoren verursachen alle möglichen Probleme und meine eigenen Programmierstandards verbietet ihre benutzen.

Verwandte Themen