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".
Related
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
How to overload operator+
(3 answers)
Closed 2 years ago.
I am learning about overloading operators in c++ and I have done this code aboout the sum of two imaginary numbers, formed by the real part and the imaginary part.
#include<iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r, int i) {
real = r;
imag = i;
}
Complex operator + (Complex const &num1, Complex const &num2) {
Complex res;
res.real = num1.real + num2.real;
res.imag = num1.imag + num2.imag;
return res;
}
void print() {
cout << real << " + i" << imag << endl;
}
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
Something should be wrong because it shows a lot of errors, notes and warnings :(
error: ‘Complex Complex::operator+(const Complex&, const Complex&)’ must take either zero or one argument
error: no match for ‘operator+’ (operand types are ‘Complex’ and ‘Complex’)
note: ‘Complex’ is not derived from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’
A binary (2 parameter) operator can't be a class member, it needs to be a standalone function instead:
class Complex {
...
public:
...
friend Complex operator + (Complex const &lhs, Complex const &rhs);
...
};
Complex operator + (Complex const &lhs, Complex const &rhs) {
return Complex(
lhs.real + rhs.real,
lhs.imag + rhs.imag
);
}
Which can also be inlined:
class Complex {
...
public:
...
friend Complex operator + (Complex const &lhs, Complex const &rhs) {
return Complex(
lhs.real + rhs.real,
lhs.imag + rhs.imag
);
}
...
};
So, a statement like c1 + c2 gets processed as operator+(c1, c2).
A unary (1 parameter) operator, on the other hand, must be a class member that acts on this as the left-side value:
class Complex {
...
public:
...
Complex operator + (Complex const &rhs) const {
return Complex(
real + rhs.real,
imag + rhs.imag
);
}
...
};
Then a statement like c1 + c2 gets processed as c1.operator+(c2).
The way you have defined operator+ is fine, expect that it needs to be a friend function. Also, note that Complex res; will not compile because you don't have a default constructor.
You could define the function like this:
friend Complex operator + (Complex const &num1, Complex const &num2) {
return {num1.real + num2.real, num1.imag + num2.imag};
}
Here's a demo.
Note also, that I fixed the bug where you are adding the imaginary part of num1 twice.
I just ran into a problem when trying to overload operator float() and operator float() const. I thought I could use both overloads to provide different versions for "do things" and "just read"... but it turns out, that with static instances of the class which contains these overloads I can't.
Boiled down the problem pretty much reduces to this:
// Does some math and should convert to float
struct ToFloat
{
// float conversion here
operator float()
{
cout << "called operator float() of " << s << "\n";
f += 1.0f;
return f;
}
// just get current value here
operator float() const
{
cout << "called operator float() *const* of " << s << "\n";
return f;
}
float f;
std::string s;
};
// Uses a static and a normal member of ToFloat
struct Container
{
// return both instances (with some more math before)
operator float()
{
return s * m;
}
// just provide read access
operator float() const
{
return s * m;
}
static inline ToFloat s { 1.0f, "static" };
ToFloat m { 1.0f, "member" };
};
// Uses the container, but must also provide read-only access
struct Use
{
// Give me operator float() of my container
float get()
{
return c;
}
// Give me operator float() const of my container
float getC() const
{
return c;
}
Container c {};
};
int main()
{
Use u {};
printf("getC() %f \n\n", u.getC());
printf("get() %f \n\n", u.get());
printf("getC() %f \n\n", u.getC());
}
Which produces the following output...
called operator float() of static
called operator float() *const* of member
getC() 2.000000
called operator float() of static
called operator float() of member
get() 6.000000
called operator float() of static
called operator float() *const* of member
getC() 8.000000
I don't really get why the static instance of ToFloat always uses the non-const conversion, even if called from a function declared const? What rule applies here?
The static data member Container::s is simply of type ToFloat. It is always accessed directly, never through an implicit dereference of this. In other words, the container's const operator is effectively this:
operator float() const
{
return Container::s * this->m;
}
From this, it should be obvious that there's no reason for Container::s to be treated as const just because this is a const Container *. If you want it to be treated as const, you have to qualify it explicitly:
operator float() const
{
return std::as_const(s) * m;
}
I have the following code where I need to add two complex numbers. Formula is working, however, I am not able to get rid of the scientific notation. I'm new to C++, and not sure how to use setPrecision.
My code in .hpp:
class ComplexNumber
{
public:
//--constructors
ComplexNumber();
ComplexNumber(double r, double i);
ComplexNumber(const ComplexNumber &cn);
void print();
ComplexNumber add(const ComplexNumber &rhs);
private:
double re, im;
};
My code in .cpp file
//--constructors
ComplexNumber::ComplexNumber()
{
}
ComplexNumber::ComplexNumber(double r, double i)
{
}
ComplexNumber::ComplexNumber(const ComplexNumber &cn)
{
}
void ComplexNumber::print()
{
std::cout << this->re << " + " << this->im << "i" << std::endl;
}
ComplexNumber ComplexNumber::add(const ComplexNumber &rhs)
{
return ComplexNumber(this-> re + rhs.re, this->im + rhs.im);
}
My main:
int main(int argc, const char * argv[]) {
ComplexNumber a(1,2);
ComplexNumber b(3,4);
ComplexNumber c;
c = a.add(b);
c.print();
return 0;
}
Output:
4.94066e-324 + 6.95322e-310i
it should be 4 + 6i
None of your constructors actually do anything. That means the member variables will be uninitialized, their values will be indeterminate and using them will lead to undefined behavior
You need to actually initialize the members in the constructors.
Works as expected after fixing the syntax (making it an aggregate):
#include <iostream>
struct ComplexNumber
{
void print();
ComplexNumber add(const ComplexNumber &rhs);
double re, im;
};
void ComplexNumber::print()
{
std::cout << this->re << " + " << this->im << "i" << std::endl;
}
ComplexNumber ComplexNumber::add(const ComplexNumber &rhs)
{
return ComplexNumber{this-> re + rhs.re, this->im + rhs.im};
}
int main(int argc, const char * argv[]) {
ComplexNumber a{1,2};
ComplexNumber b{3,4};
ComplexNumber c;
c = a.add(b);
c.print();
return 0;
}
Precision is not the issue here.
Your two-argument constructor needs to be implemented as follows
ComplexNumber::ComplexNumber(double r, double i) : re(r), im(i)
{
}
otherwise the class members stay uninitialised.
Reading uninitialised variables is undefined behaviour in C++; your output is a manifestation of that.
It's stylistically acceptable (and in my opinion preferable for a number class) to write
ComplexNumber() = default;
for your default constructor; if you want it to keep the class members uninitialised, as is the case for the C++ built-in types. Just don't read the member variables before assigning them to something.
Finally, rely on the compiler to generate the copy constructor for you: there's no need to build your own.
What operators I need to overload to make this word?
Variables A1 and A2 both of type class A, variable floatValue is of type float.
A1 += A2 * floatValue;
I have overloaded this operators
A operator+() const;
A operator+=(const A value);
A operator*(const A value);
friend A operator*(const A val2, float val);
But, I receive error "Class A has no suitable copy constructor"
I have this constructors in my class
A();
A(float val1, float val2);
A(float value);
Thanks for answering.
Minimal example:
#include <iostream>
using namespace std;
struct foo {
float val;
foo(float val): val(val){}
foo &operator+=(foo const &other) {
this->val += other.val;
return *this;
}
friend foo operator*(foo const &lhs, foo const &rhs) {
return lhs.val*rhs.val;
}
};
int main() {
foo a = 5, b = 6;
a += b * 3;
cout << a.val << endl;
return 0;
}
see: http://ideone.com/6pD2pr
With an explicit constructor you might want to use this example instead:
#include <iostream>
using namespace std;
struct foo {
float val;
explicit foo(float val): val(val){}
foo &operator+=(foo const &other) {
this->val += other.val;
return *this;
}
friend foo operator*(foo const &lhs, float val) {
return foo(lhs.val*val);
}
};
int main() {
foo a(5), b(6);
a += b * 3;
cout << a.val << endl;
return 0;
}
see: http://ideone.com/o8Vu1d
Whenever you overload an assignment operator like
A operator+=(const A value);
you also need to define a copy constructor like
A( const A& );
The copy constructor will be used by the assignment operator.
This is part of what's known as the Rule of Three.
When you have function like this:
fun(A a);
Arguments here are passed by value, so you need to have copy constructor for A (in order to create new instance from another instance), OR you can change it to reference, so no copy constructor will be needed.
Like this:
A operator+=(const A &value);
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;
}