class B{
float floatVar;
public:
B(float a):floatVar(0.0){
floatVar = a;
}
operator int(){ // Consider this as line A
return floatVar;
}
};
int main()
{
B floatObj(5.5);
cout << floatObj; // Consider this as line B
return 0;
}
when i cout while overloading int() it displays 5 and when i replace int() with float() in line A , program displays 5.5.
I want to know how it is automatically calling the int() typecaster or the float() in cout?
There is no synthesis of default printing function or alike in C++, thus defining a class with some fields doesn't print them by default if you try to print an objet of the class.
As you didn't defined any overloaded operator << to print to some ostream (like cout) the compiler found a way to print it through the defined conversion to int.
Compiler is allowed to perform one user-defined conversion implicitly when searching for matching function overload. Since you provide conversion from B to int, compiler can use that and select operator <<(std::ostream, int) overload of the << operator for std::cout.
If you would add another conversion to a type that is accepted by operator << for std::ostream (e.g. float), compiler would say that it is ambiguous call and it cannot choose by itself.
class B{
float floatVar;
public:
B(float a):floatVar(0.0){
floatVar = a;
}
operator int(){
return floatVar;
}
operator float(){
return floatVar;
}
};
int main()
{
B floatObj(5.5);
cout << floatObj; //error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'B')
cout << static_cast<int>(floatObj); //explicit conversion, compiles
return 0;
}
Related
#include <iostream>
#include <cmath>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
// Default constructor
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i)
{}
// magnitude : usual function style
double mag()
{
return getMag();
}
// magnitude : conversion operator
operator int ()
{
return getMag();
}
private:
// class helper to get magnitude
double getMag()
{
return sqrt(real * real + imag * imag);
}
};
int main()
{
// a Complex object
Complex com(3.0, 4.0);
// print magnitude
cout << com.mag() << endl;
// same can be done like this
cout << com << endl;
}
I don't understand how the compiler is resolving to call the conversion operator for cout << com << endl;.
I can also have more than one conversion operator in the same class. How will the resolution be done in that case?
You have declared a conversion operator to int. Since this operator is not explicit, the compiler considers it when finding the best overload of ostream::operator<<. Keep in mind that C++ compiler always attempts to automatically convert types to find a matching call, including conversion constructors, conversion operators and implicit type conversions.
If you do not want this behavior, then starting from C++11 you can mark the operator as explicit:
explicit operator int() {
return getMag();
}
Regarding the second part of your question, if there are multiple conversions that are equally good, a compile error is invoked. If you added, say, operator double, then as there exists ostream::operator(double), the call would be ambiguous and you would need to cast com to Your desired type.
I supose that the compiler tries to convert to a type for which cout has an overload defined.
If it can be converted to 2 types for which cout has an overload defined you will get a compilation error.
If you add this function to the class code won't compile:
// magnitude : conversion operator
operator float ()
{
return getMag() + 1;
}
To solve that you must do a cast like that:
// same can be done like this
cout << "Com: " << (float) com << endl;
I am studying converting constructors and conversion operators in C++.
What I've learned so far is that any non-explicit constructor that takes only one parameter (and any number of optional default arguments) represents an implicit class-type conversion to THAT class type, for example if a class defines a constructor that has one parameter of type int I can use an int wherever an object of that class type is required:
(assuming class_type has an overloaded += operator)
class_type a;
a+=5;
in this case 5 is implicitly converted (through the converting constructor) to class_typeand the overloaded operator is called.
Now, the (at least for me) tricky part: I know I can define a conversion operator as a member function :
operator int() {....};
that converts the object of class_type to the primitive int type, and I can use that conversion like:
class_type a;
a+5;
in this case I've read that the object is converted to an int through its conversion operator and then the buil-in sum operator is called.
But what if I defined an overloaded + operator to take two class_type objects as its arguments? something like
class_type operator+(const class_type&,const class_type &c);
how is the compiler supposed to know which one to call through function matching?
does the conversion to int only happens implicitly when only the built-in operator is defined?
thanks!
edit:
actually,I've tried to write some code to effectively try it out, it turned out that my compiler (g++) doesn't issue any ambiguous call error!
this is the class header (along with the non-memeber operator+ function declaration) :
#include <iostream>
class wrapper {
friend std::ostream &operator<<(std::ostream&,const wrapper&);
public:
wrapper()=default;
wrapper(int);
int get();
operator int() const;
wrapper operator+(int);
private:
int a=10;
};
std::ostream &operator<<(std::ostream&,const wrapper&);
and this is the main code:
#include "wrapper.h"
int main()
{
using namespace std;
wrapper w1;
wrapper w2(5);
cout<<w1<<" "<<w2<<endl;
w1+1;
}
now,I've defined a converting constructor from int to wrapper AND a conversion operator from class type to int(I've also overloaded the << output operator in order to print some results), but when the compiler evaluates the expression w1+1 it seems to be fine. How could it possibly be??
If you have for example the following class declaration that contains a conversion constructor and a conversion operator
struct A
{
A( int x ) : x( x ) {}
operator int() const { return x; }
int x;
};
const A operator +( const A &a1, const A &a2 )
{
return A( a1.x + a2.x );
}
then statement
a1 + a2;
where a1 and a2 are declared like for example
A a1( 10 );
A a2( 20 );
will be well-formed because there is no need to call a conversion function. The both operands match the parameter declarations of the operator +.
However if you will write for example
a1 + 20;
when the compiler issues an error because there is an ambiguity. The compiler can either apply conversion constructor A( int ) to convert the second operand to type A and call the operator defined for objects of type A. Or it can apply the conversion operator operator int to convert the first operand to type int and call the built-in operator + for objects of type int.
To avoid this ambiguity you could declare either the constructor or the operator (or the both) with function specifier explicit.
For example
explicit A( int x ) : x( x ) {}
or
explicit operator int() const { return x; }
In this case only one implicit conversion would exist and there was not an ambigiuty.
I would like to append the above description that sometimes some converion operators can be called implicitly even if they are declared with the function specifier explicit.
For example According to the C++ Standard (6.4 Selection statements)
...The value of a condition that is an expression is the value of the
expression, contextually converted to bool for statements other
than switch;
and (5.16 Conditional operator)
1 Conditional expressions group right-to-left. The first expression is
contextually converted to bool (Clause 4).
So for example if the above class has the following conversion operator declared with the function specifier explicit
explicit operator bool() const { return x != 0; }
nevertheless it will be called implicitly for example in the following statement
A a( 10 );
std::cout << ( a ? "true" : "false" ) << std::endl;
Here a will be converted to an object of type bool in the conditional operator.
EDIT: After you updated your question this expression
w1+1;
is an exact match for operator
wrapper operator+(int);
Neither conversion are required. So the code compiles successfully.
This is something you can easily try and see what the compiler does:
#include <iostream>
struct ABC {
int v;
ABC(int x) : v(x) { }
operator int() const { return v; }
void operator +=(ABC const &that) {
v += that.v;
}
};
ABC operator+(ABC const &lhs, ABC const &rhs) {
return { lhs.v + rhs.v };
}
int main() {
ABC a(5);
std::cout << a + 1 << '\n';
a += 10;
std::cout << a << '\n';
}
what if I defined an overloaded + operator to take two class_type objects as its arguments?
GCC
error: ambiguous overload for 'operator+' (operand types are 'ABC' and 'int')
The compiler sees two candidates: operator+(int, int) <built-in> and ABC operator+(const ABC&, const ABC&). This means it could implicitly convert not only the 5 in a + 5 to a but also the a to int. Post these conversions both operator+ functions become potential matches.
How is the compiler supposed to know which one to call through function matching?
It doesn't know hence the error.
does the conversion to int only happens implicitly when only the built-in operator is defined?
Yes, otherwise it doesn't automatically convert class_type to int. However, int to class_type would happen implicitly unless you make class_type's constructor explicit:
explicit ABC(int x) : v(x) { }
If you've access to C++11, then you also make the conversion function explicit:
explicit operator int() const { return v; }
'int' and 'double' conversion functions is 'explicit' and in this code why have I permit for use this conversion instead of error message?
If I delete all my conversion overload functions code occur 'conversion error'
class Person
{
public:
Person(string s = "", int age = 0) :Name(s), Age(age) {}
operator string() const { return Name; }
explicit operator int() const{ return 10; } // ! Explicit
explicit operator double()const { return 20; } //! Explicit
operator bool()const { if (Name != "") return true; return false; } // using this
};
int main(){
Person a;
int z = a;
std::cout << z << std::endl; // Why print "1"? Why uses bool conversion?
}
I this it is answer:
Because 'a' can not be convert to int or double it occur error, but because it has bool conversion function, which can convert to int and int to double, code use this function.
int z = a;
Looks innocuous, right?
Well, the above line calls the implicit bool-conversion-operator, because that's the only way you left it to get from Person to int, and that only needs one user-defined conversion (the maximum allowed).
This is the reason for the safe-bool-idiom before C++11, and the major reason for the general advice to mark conversion operators and single-argument ctors explicit unless they are not transformative nor lossy.
If you want to see it for yourself, fix your code and trace invocation of your operator bool.
I run into a strange c++ operator.
http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f0097af7530fe57a100b00d
class Number {
..
operator unsigned short () const;
};
I called this operator as:
a Number(..);
unsigned short b = a.operator unsigned short();
this works, but I can't understand how it works.
first, this operator don't have a return value.
seconds, a.operator unsigned short() is really strange to me. What is a better way to call this?
if I call :
unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
The function is a user defined conversion operator. More details can be found at http://en.cppreference.com/w/cpp/language/cast_operator.
You said,
this operator don't have a return value. seconds,
The return values of the user define conversion operators is the explicit type. In your case, the return type is unsigned short.
You asked:
What is a better way to call this?
You could do an explicit cast to invoke the function.
Number n;
unsigned short s = (unsigned short)v;
It is also called when an conversion is required by the compiler.
void foo(unsigned short s) {}
Number n;
foo(n); // Number::operator unsigned short() is called to cast
// n to an unsigned short.
You asked:
if I call : unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
Yes. The user defined operator function gets called.
Here's the relevant sections from the C++ Draft Standard (N3337):
12.3.2 Conversion functions
1 A member function of a class X having no parameters with a name of the form
...
[ Example:
struct X {
operator int();
};
void f(X a) {
int i = int(a);
i = (int)a;
i = a;
}
In all three cases the value assigned will be converted by X::operator int(). — end example ]
This is the conversion operator. A conversion function typically has the general form
operator type() const;
where type represents a type. It means objects of type Number can be converted to short int.
The conversion operator have no explicitly stated return type and no parameters, because the return type is exactly the type in the signature.
It's a conversion function, called to convert your type into a specific other type under various conditions, and it's covered in ISO C++11 12.3.2 Conversion functions.
In your case, it's called when the Number instance needs to be converted into an unsigned short.
By providing conversion operators, you can take full control over what happens during the conversion process, including such evil as the following:
#include <iostream>
struct X {
int val;
X(int v) { val = v; };
operator int() { return val + 1; }; // pure evil
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
int main (void) {
X xyzzy (42);;
std::cout << xyzzy << '\n';
std::cout << (int)xyzzy << '\n';
return 0;
}
which will output the value when you use the instance directly, but output something totally different when you cast it.
Now granted, that's rather evil and not a really good use case but you can use this for things such as rounding floats rather than truncating them, when converting to an integer:
#include <iostream>
struct X {
double val;
X(double v) { val = v; };
operator int() { return (int)(val + 0.5); };
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
#define E 2.718281828456
int main (void) {
X xyzzy (E);
double plugh = E;
std::cout << plugh << " -> " << (int)plugh << '\n';
std::cout << xyzzy << " -> " << (int)xyzzy << '\n';
return 0;
}
The output of that code is:
2.71828 -> 2
2.71828 -> 3
As a supplement for the first answer, when you use keyword explicit, note the difference, using explicit would force the programmer to assert his intention to convert using a cast:
class Number {
private:
int num;
public:
explicit Number(int number) : num(number) {} // constructor
explicit operator unsigned short () const { // conversion operator
return num;
}
};
int main() {
Number classTypeNumber(10);
// unsigned short convertToUshortNumber = classTypeNumber; // error
// implicit conversion is not allowed.
// now you should explicit convert the instance first.
// typedef unsigned short int __u_short in types.h file.
unsigned short convertToUshortNumber = static_cast<__u_short>(classTypeNumber);
cout << convertToUshortNumber;
}
I'm trying to overload the + operator in C++, but get the following error:
operators.cpp: In function ‘int main()’:
operators.cpp: 23:17: error: cannot convert ‘Operators’ to ‘int’ in initialization
This is my code:
#include <iostream>
using namespace std;
class Operators{
private:
int num1;
public:
Operators(int num1){
this->num1 = num1;
}
Operators operator+(Operators o){
return Operators(num1 + o.num1);
}
};
int main(){
Operators o1(5);
Operators o2(10);
Operators res = o1 + o2; // EDITED
cout << res;
}
Could you please help me?
I know, in this case it doesn't make sense to overload it, as I could just say 5+10, but I'm just experimenting.
UPDATE
Thanks, I've edited the int.
But now I'm getting the following error:
operators.cpp: In function ‘int main()’:
operators.cpp: 25:10: error: match for ‘operator<<’ in ‘std::cout << res’
[...]
The problem with this line:
int res = o1 + o2;
Is that your overload of operator + returns an object of type Operators. This means that you are trying to initialize an int (res) from a temporary of type Operators (the result of o1 + o2), but there is no user-defined conversion for doing that.
This is why the compiler is issuing an error. You can fix this easily by adding a conversion operator to your Operators class:
operator int () const { return num1; }
UPDATE:
It seems you have updated your question. The second line below is problematic:
Operators res = o1 + o2;
cout << res;
Unless you defined an overload of operator << for your Operators class, the compiler won't know which overload of operator << to pick for streaming your object of type Operators.
To solve the issue, you can:
Define a conversion operator to int, as suggested above
Define an overload of operator << for Operators, as follows:
friend std::ostream& operator << (std::ostream& o, Operators const& op)
{
o << op.num1;
return o;
}
Here is a live example.
As the error message is trying to tell you, o1 + o2 is of type Operators.
You can't assign that to an int
Your operator+ returns an Operators object. You then try and assign this result to int res. YOu have given no way to convert from an Operators object to an int. You could provide a conversion operator to do this:
operator int() {
return num1;
}
This defines a conversion from Operators to int.
You need to write:
int res = o1.getMethod() + o2.getMethod();
where getMethod() is a public method in your class that returns the private integer num1.
Otherwise, you don't have access to it. Try it.
Change int to Operators, and implement your own copy and default constructor.
#include <iostream>
class Operators
{
private:
int num1;
public:
Operators() = default;
Operators(Operators const& op) : num1(op.num1) {}
Operators(int num1)
{
this->num1 = num1;
}
Operators operator+(Operators o)
{
return num1 + o.num1;
}
};
int main()
{
Operators o1(5);
Operators o2(10), res;
res = o1 + o2;
std::cout << res;
}
To make this work further, create an overload of operator<< and print the sum.