2015-09-16 7 views
12

Ich habe eine Rectangle Klasse mit Konvertierungsoperatoren sowohl auf double und std::string:Unklare Verwendung von Operator double()

class Rectangle 
{ 
public: 
    Rectangle(double x, double y) : _x(x), _y(y) {} 
    operator std::string(); 
    operator double(); 
private: 
    double _x, _y; 
    double getArea() {return _x * _y;} 
}; 

int main() 
{ 
    Rectangle r(3, 2.5); 
    cout << r << endl; 
    return 0; 
} 

Ich verstehe nicht, warum operator double() aufgerufen wird, anstatt operator std::string(). Soweit ich weiß, C++ wikibook, operator double wird verwendet, um Rectangle Objekte zu double zu konvertieren.

Also, was ist hier los? Ist es mit der Tatsache verbunden, dass ein int an den Konstruktor übergeben wird? Wenn ja warum?

+0

Was bedeutet es sogar, ein Rechteck in ein Doppel zu konvertieren. –

+0

ich denke (double) r oder sowas –

+2

@AlexGoft Nein, der andere Alex meinte "was heißt das logisch *?". Auf den ersten Blick erscheint die Operation bedeutungslos. –

Antwort

11

Sie haben keinen Operator, um das Rechteck an den Stream auszugeben. cout hat eine Überladung, die eine double dauert und Ihre Klasse kann implizit in eine double konvertiert werden, so dass gewählt wird.

Der Grund die String Überlastung nicht gewählt ist und nicht als eine Mehrdeutigkeit betrachtet, weil operator << für eine Zeichenfolge ein Funktionselement ist und nicht in dem member overload und non member overload Satz von cout enthalten. Wenn wir die kommentieren, können wir we get a compiler error sehen.

Wenn wir die operator string aufgerufen haben möchten, müssten wir r explizit in eine Zeichenfolge umwandeln. Live Example

+3

Warum wählt es dann nicht die 'string' Umwandlung? – interjay

+0

@interjay Ich habe gerade nachgedacht. Ich habe diesen Operator nicht gesehen, als ich die Antwort schrieb, – NathanOliver

+6

Netter Fang. Wenn man erklären wollte, warum die Implementierung von 'operator double()' auf Typen, die keine Zahl darstellen, eine schlechte Übung ist, würde er sich schwer tun, eine bessere Illustration zu finden :-) – dasblinkenlight

6

Da Sie eine operator<< Überlastung für Rectangle nicht vorsah, hält der Compiler andere Überlastungen, für die die Argumente für die Parametertypen umgewandelt werden.

Wenn eine der Überladungen Vorlagen sind, wird ihnen vor der Überladungsauflösung eine Template-Argumentsubstitution zugewiesen. Der Compiler versucht, die Template-Parameter aus den Typen der Argumente abzuleiten, die der Funktion übergeben werden.

Die string Überlastung ist nicht wegen eines Template-Argument Substitution Versagen betrachtet:

template <class CharT, class Traits, class Allocator> 
std::basic_ostream<CharT, Traits>& 
    operator<<(std::basic_ostream<CharT, Traits>& os, 
       const std::basic_string<CharT, Traits, Allocator>& str); 

Vorlage Argument Substitution nicht benutzerdefinierte Konvertierungen nicht berücksichtigt, so dass der Compiler die Typen CharT nicht ableiten kann, Traits oder Allocator vom Typ Rectangle, so dass diese Überladung nicht an der Überladungsauflösung beteiligt ist. (Es sei daran erinnert, dass std::string ist nur ein typedef von std::basic_string<char, std::char_traits<char>, std::allocator<char>>.)

Daher besteht eine Überlastung der operator<< ist, die eine bessere Übereinstimmung als andere ist, und das ist die double Überlastung. Keine Vorlage, sondern eine Mitgliedsfunktion einer Klassenvorlage.

basic_ostream<CharT, Traits>& basic_ostream<CharT, Traits>::operator<<(double); 
+0

Beachten Sie, dass die letzte Vorlage trivial ist; 'std :: cout' erbt von' std :: basic_ostream > '. Die Ersetzung von Template-Argumenten ist nicht erforderlich. – MSalters