conversion constructor calling function with no argument - c++

How conversion constructor is getting used in following program
#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 double ()
{
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 am not able to understand that why statement "cout << com << endl;"calling funtion mag(). Please help. if I change function mag() to mag (int i) then also , same output.

mag() is never called. Your double conversion operator calls getMag() which is why it appears that mag() is being called.
When you call cout << com << endl there is no overloaded operator << for your Complex class. This causes the compiler to look for implicit conversions to something operator << supports. Your complex class has overloaded the double conversion operator here:
operator double ()
{
return getMag();
}
As you can see the double conversion operator calls getMag() and this it why it appears that mag() is being called.

The statement
cout<<com<<endl;
does not call Complex::mag(). It is calling the convertion operator operator double();

The class has conversion operator
operator double ()
{
return getMag();
}
So if you have an object of type Complex named com then in statement
std::cout << com << std::endl;
there will be called the conversion operator that converts object com to an object of type double.
If you will declare the operator with specifier explicit
explicit operator double ()
{
return getMag();
}
then the statement above will not compile.

Related

C++ type conversion operator

I am studying operator overloading, there are some parts that are difficult to understand.
See this example code.
class A {
private:
char a;
int b;
double c;
public:
A(char _a = 'a', int _b = 99, double _c = 1.618) :a(_a), b(_b), c(_c){
}
public:
operator char() const {
cout << "operator char() called" << endl;
return this->a;
}
operator int() const {
cout << "operator int() called" << endl;
return this->b;
}
operator double() {
cout << "operator double() called" << endl;
return this->c;
}
};
int main(void) {
A a;
char b = a;
int c = a;
double d = a;
printf("%c\n", b);
printf("%d\n", c);
printf("%f\n", d);
return 0;
}
I made this code to test for type conversion operator and expected that the appropriate function would be called for each type of data.
But the result is..
operator double() called
operator double() called
operator double() called
<-- strange character is gone on board!
1
1.618000
I can not understand why the results are not as follows.
operator char() called
operator int() called
operator double() called
a
99
1.618
Why is double operator called when converting to char and int?
Have a good day! :)
You forgot the const on the double conversion operator:
operator double() const { // <---------------------------
cout << "operator double() called" << endl;
return this->c;
}
};
As in your example a is not const, the double conversion is the best match. If you fix that you get the expected output.
Live example
...some opinion based PS:
I didnt find what the core guidelines say about conversion operators, but if I had to make up a guideline for conversion operators it would be: Avoid them. If you use them, make them explicit. The surprising effects of implicit conversion outweigh the benefits by far.
Just as an example, consider std::bitset. Instead of offering conversion operators it has to_string, to_ulong and to_ullong. It is better to have your code explicit. A a; double d = a; is a little bit mysterious. I would have to look at the class definition to get an idea of what is really going on. On the other hand A a; double d = a.as_double(); can do the exact same thing, but is way more expressive.
Yea so the problem is, that you made all operators const except for the double operator. I am still a bit surprised because this const just means that the operator call does not modify the class members. Still it seems that only the double operator is called for all 3. I would all 3 op's make const and then it will work properly.
If someone has an explanation why this happens, I would also like to know.
Cheers.
operator char() const { // here is const
cout << "operator char() called" << endl;
return this->a;
}
operator int() const { // here is const
cout << "operator int() called" << endl;
return this->b;
}
operator double() { // here is no const
cout << "operator double() called" << endl;
return this->c;
}

Using the constructor to transform variable into object in c++

int main()
{
CComplex c1(9,9);
CComplex c3;
c3 = 5 + c1; // getting error here
c3.print();
cout << c3;
return 0;
}
CComplex CComplex::operator+(const CComplex &complex)
{
CComplex temp;
temp.m_real = complex.m_real + m_real;
temp.m_imaginary = complex.m_imaginary + m_imaginary;
return temp;
}
You need overload + operator for int type and add some constructors if they are not defined
class CComplex
{
public:
CComplex()
: m_real(0), m_imaginary(0)
{ }
CComplex(double real)
: m_real(real), m_imaginary(0)
{ }
CComplex(double real, double imaginary)
: m_real(real), m_imaginary(imaginary)
{ }
CComplex operator + (const CComplex& complex)
{
CComplex temp;
temp.m_real = complex.m_real + m_real;
temp.m_imaginary = complex.m_imaginary + m_imaginary;
return temp;
}
double m_real;
double m_imaginary;
};
CComplex operator + (const int value, const CComplex& complex)
{
return CComplex(value) + complex;
}
std::ostream& operator << (std::ostream& os, const CComplex& complex)
{
os << "(" << complex.m_real << "," << complex.m_imaginary << ")";
return os;
}
int main()
{
CComplex c1(9,9);
CComplex c3;
c3 = 5 + c1; // no more error here
std::cout << c3;
return 0;
}
Result
(14,9)
I think the correct solution is:
class CComplex {
public:
CComplex();
CComplex(int); // NEW - CONVERSION CONSTRUCTOR
CComplex(double real);
CComplex(double real, double imaginary);
friend CComplex operator + (const CComplex& a, const CComplex& b); // FRIEND - NON-MEMBER FUNCTION
};
Please note these features in the code:
There is a constructor getting one int parameter. This is a casting constructor that the compiler can use for automatic conversion from an int to CComplex.
operator+ is a non-member function (friend keyword makes the function non-member). It slightly differs from the situation when operator+ is a member function (CComplex operator+(CComplex const &b) const).
If you write:
CComplex c1;
5 + c1;
Then for 5 + c1 there is searched an operator+ with parameters (int,CComplex). According to C++ standard there is allowed only one conversion to get proper parameter types (sorry I have no formal quotation). There is a conversion constructor from int to CComplex so there is automatically called this conversion constructor and then operator+(CComplex,CComplex) with proper parameters.
If you didn't have CComplex(int) constructor, then 5 + c1 would not work because there are needed TWO conversion from: int to double and from double to CComplex.
Additionaly, if operator+ was a member function (not friend), it wouldn't work at all. Because according C++ standard there is no possibility of automatic conversion for the left operand. So even conversion constructor CComplex(int) wouldn't help.
Plus: I think that overloading operator+ for types like (int, CComplex) is not a good idea because it would cause explosion of declarations. The same you would need for operator-() and for any order of operands - e.g. (CComplex,int), (CComplex,long), etc... By providing conversion constructor from required types you get all these combinations "automatically" and "for free".

operator= in c++ (11) working direction

I'm doing a Little rational class for my Project and I overload all aritmethic operators. Well, when I try to overload operator= I have a Little and now I don't know if is my problem (i don't know how it Works) or problem of my wroten code (i wrote it bad) here's the code:
class rational{
public:
double& operator=(double& d){
d= this->num/this->den;
return d;
}
double& operator=(rational& r){
double d= r.num/r.den;
return d;
}
double& operator=(){
double d= this->num/this->den;
return d;
}
}
Ok, what's wrong? what's right? (i think that all is wrong haha)
My goal is do that:
int main(){
rational r(4, 5);
double d= r;
}
Can I do it? if yes, how?
You don't want an assignment operator for this purpose - you should instead overload a conversion operator; e.g.
class rational {
private:
int num;
int den;
public:
// ...
operator double() { return double(num) / double(den); }
};
This will allow
rational r(4, 5);
double d = double(r); // d = 0.8
The assignment operators should be used for changing the state of an existing object, if that's something you want to allow. You probably would not want to allow assignment of a double to a rational there is no unambiguous meaning for such an operation. However, you might want to provide helpers for assigning an int, say, in addition to the usual one for assigning another rational:
rational &operator=(const rational &rhs)
{
num = rhs.num;
den = rhs.den;
return *this;
}
rational &operator=(int rhs)
{
num = rhs;
den = 1;
return *this;
}
Here I think a user-defined conversion operator would be more appropriate.
class rational {
public:
rational( int iNum, int iDen ) : num( iNum ), den( iDen ) {}
// ...
operator double() { return (double)num / (double)den; }
private:
int num;
int den;
};
int main()
{
rational r( 1, 2 );
double n = r;
std::cout << r << std::endl; // output 0.5
return 0;
}
Here is a little live example to illustrate this : http://ideone.com/I0Oj66
About the copy assignment operator= :
A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter of type T.
The operator= is used to change an existing object.
You can use it for example to copy the state of another object :
rational &operator=( const rational &rhs )
{
num = rhs.num;
den = rhs.den;
return *this;
}

OOP C++ first compiler error

Please help this newbie, here's my code:
#include <iostream>
using namespace std;
class Complex {
private:
float r, i;
public:
Complex(float rr, float ii) : r(rr), i (ii) {}
float GiveRe () { return r; }
float GiveIm () { return i; }
void Setit (float rr, float ii) {
r = rr;
i = ii;
}
};
Complex a(10, 20);
Complex sumit (Complex &ref) {
static Complex sum (0, 0);
sum.Setit(sum.GiveRe() + ref.GiveRe(), sum.GiveIm() + ref.GiveIm());
return sum;
}
int main () {
Complex sumvalue = sumit (a);
cout << sumvalue << endl;
return 0;
}
error: no match for 'operator<<' in 'std::cout << sumvalue'.
The program should output the sum of a complex number.
cout can't tell what you want to output, you need to specify the operator<< in the class or make it possible to implicitly convert your class to a compatible type.
http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/
Rudolf Mühlbauer's code as implemented in your class:
Add this somewhere within the class header:
friend ostream& operator<<(ostream& out, const Complex& compl);
and this below the header:
ostream& operator<<(ostream& out, const Complex& compl)
{
return out << compl.r << "/" << compl.i;
}
Implementation should be changed to suit your exact needs.
Complex doesn't have an operator <<
ostream& Complex::operator << ( ostream& os )
{
// use os << field/method here to out put
return os;
}
Also if complex can be displayed to console in different ways, then you should think of using methods to display instead of cout <<
void Complex::DisplayToConsole()
{
std::cout << r << " " << i << '\n';
}
You have to overload the "<<" operator for Complex type.
#include <iostream>
using namespace std;
class Complex {
private:
float r, i;
public:
Complex(float rr, float ii) : r(rr), i (ii) {}
float GiveRe () { return r; }
float GiveIm () { return i; }
void Setit (float rr, float ii) {
r = rr;
i = ii;
}
};
ostream& operator<<(ostream& os, Complex& c)
{
float i;
os<<c.GiveRe();
if(c.GiveIm() < 0){
os<<"-j"<<c.GiveIm()*(-1);
}else{
os<<"+j"<<c.GiveIm();
}
return os;
}
Complex a(10, 20);
Complex sumit (Complex &ref) {
static Complex sum (0, 0);
sum.Setit(sum.GiveRe() + ref.GiveRe(), sum.GiveIm() + ref.GiveIm());
return sum;
}
int main () {
Complex sumvalue = sumit (a);
cout << sumvalue << endl;
return 0;
}
A complete minimal example:
#include <iostream>
using namespace std;
class C {
public:
int r, l;
// if the operator needs access to private fields:
friend ostream& operator<< (ostream&, const C&);
};
ostream& operator << (ostream& stream, const C& c) {
stream << c.r << "--" << c.l;
return stream;
}
int main() {
C c;
c.l = 1;
c.r = 2;
cout << c << endl;
}
C++ allows you to define operators. The STL uses the << operator for output, and the whole istream/ostream class hierarchy uses this operator to input/output.
Operators are implemented as functions, but always follow a very specific syntax. As in the example, ostream& operator << (ostream&, const MYTYPEHERE&) is the way to define ostream << operators.
When C++ encounters a statement, it has to deduce the types of all operands, and find (quite magically, indeed) a solution to the question: given my operands and operators, can i find a typing such that the statement gets valid?
These ofstream operators are defined for all basic types somewhere in <iostream>, so if you write cout << 10, the compiler finds an operator ostream& operator<< (ostream&, int).
If you want to be able to use userdefined types in this game, you have to define the operators. otherwise, a statement cout << sometype will not be valid. This is also the reason for the harsh compiler errors sometimes found in C++: "Well, i have some operators << defined, but none is compatible with your type!".
Because sometimes it is not favourable to implement operators for your types (if you only output them once, e.g.), i suggested to write:
cout << sum.re << "--" << sum.im << endl; // or similar
This way, you write less code, and you are flexible in the output format. Who knows if you want you complex number formatted differently next time? But this is another discussion.
Why complicating that much? Because C++ can be awfully complicated. It it very powerfull, but crammed with special syntax and exceptions to those. In the end, the difference to C lies exactly here: C++ does a much better job with type inference (needed for templates), often resulting in WTF?
On how to implement it in your code, i think the other answers provide nice solutions!
sumit(a) returns an object of type Complex, which cout was not defined to handle.

Why doesn't my overloaded comma operator get called?

I'm trying to overload the comma operator with a non-friend non-member function like this:
#include <iostream>
using std::cout;
using std::endl;
class comma_op
{
int val;
public:
void operator,(const float &rhs)
{
cout << this->val << ", " << rhs << endl;
}
};
void operator,(const float &lhs, const comma_op &rhs)
{
cout << "Reached!\n"; // this gets printed though
rhs, lhs; // reversing this leads to a infinite recursion ;)
}
int main()
{
comma_op obj;
12.5f, obj;
return 0;
}
Basically, I'm trying to get the comma operator usable from both sides, with a float. Having a member function only allows me to write obj, float_val, while having an additional helper non-friend non-member function allows me to write float_val, obj; but the member operator function doesn't get called.
GCC cries:
comma.cpp: In function ‘void operator,(const float&, const comma_op&)’:
comma.cpp:19: warning: left-hand operand of comma has no effect
comma.cpp:19: warning: right-hand operand of comma has no effect
Note:
I realise that overloading operators, that too to overload comma op., Is confusing and is not at all advisable from a purist's viewpoint. I'm just learning C++ nuances here.
void operator,(const float &rhs)
You need a const here.
void operator,(const float &rhs) const {
cout << this->val << ", " << rhs << endl;
}
The reason is because
rhs, lhs
will call
rhs.operator,(lhs)
Since rhs is a const comma_op&, the method must be a const method. But you only provide a non-const operator,, so the default definition will be used.