I have a Rectangle
class with conversion operators to both double
and std::string
:
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;
}
I don’t understand why operator double()
is invoked, rather than operator std::string()
.
As far as I know, according to C++ wikibook,
operator double
is used to convert Rectangle
objects to double
.
So what's going on here? Is it related to the fact that an int
is passed to the constructor? If so, why?
This method returns the object's value as a double. This method hands the value of the object back to the caller as a double. If the object's current value is not a double, the method attempts to convert the value.
RE your edits: No, you can't. There is no such thing as operator overloading in C. You cannot define custom operators to work with your structs, in any way, at all, in C. Operator overloading is something you do in C++, it has nothing what so ever to do with C.
In C++, we can change the way operators work for user-defined types like objects and structures. This is known as operator overloading. For example, Suppose we have created three objects c1 , c2 and result from a class named Complex that represents complex numbers.
In programming, an operator is a symbol that operates on a value or a variable. Operators are symbols that perform operations on variables and values. For example, + is an operator used for addition, while - is an operator used for subtraction.
You do not have an operator to output the rectangle to the stream. cout
does have an overload that takes a double
and your class can be implicitly converted to a double
so that is chosen.
The reason the string overload is not selected and is not considered as an ambiguity is because operator <<
for a string is a member function and is not included in the member overload and non member overload set of cout
. If we comment out the operator double
we can see we get a compiler error.
If we want to have the operator string
called then we would need to explicitly cast r
into a string. Live Example
Since you did not provide an operator<<
overload for Rectangle
, the compiler considers other overloads for which the arguments can be converted to the parameter types.
If any of the overloads are templates, then template argument substitution happens to them before overload resolution. The compiler tries to deduce the template parameters from the types of the arguments supplied to the function.
The string
overload is not considered because of a template argument substitution failure:
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);
Template argument substitution does not consider user-defined conversions, so the compiler can't deduce the types CharT
, Traits
, or Allocator
from the type Rectangle
, so this overload does not participate in overload resolution. (Recall that std::string
is just a typedef of std::basic_string<char, std::char_traits<char>, std::allocator<char>>
.)
Therefore there is one overload of operator<<
which is a better match than any other, and that is the double
overload. Not a template, but a member function of a class template.
basic_ostream<CharT, Traits>& basic_ostream<CharT, Traits>::operator<<(double);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With