Overloading operator fails ?

  • Thread starter Matthias Pospiech
  • Start date
M

Matthias Pospiech

I have a Class for complex operations:

class CComplex
{
public:
inline CComplex() { re=im=0.0; }
inline CComplex operator*(CComplex c) { return
CComplex(re*c.re-im*c.im,re*c.im+im*c.re);}
inline CComplex operator*(double &d) { return CComplex(re*d,im*d);}
double re,im;
};

However when multiplying double * CComplex the operation fails

double m_Phase[8192][8192]; // Phase of Field
double m_Amplitude[8192][8192]; // Amplitude of Field
CComplex m_Field[8192][8192]; // Full electric Field

CComplex Expi(double wt) {return CComplex(cos(wt),sin(wt));}
CComplex Expi(CComplex x) {return

m_Field[x][y]= (m_Amplitude[x][y]) * (Expi(m_Phase[x][y]));


with

error C2677: Binärer Operator '*': Es konnte kein globaler Operator
gefunden werden, der den Typ 'CComplex' akzeptiert (oder keine geeignete
Konvertierung möglich)

(no Operator found that accepts CComplex)

What is going wrong ??

Matthias
 
E

eriwik

I have a Class for complex operations:

class CComplex
{
public:
inline CComplex() { re=im=0.0; }
inline CComplex operator*(CComplex c) { return
CComplex(re*c.re-im*c.im,re*c.im+im*c.re);}
inline CComplex operator*(double &d) { return CComplex(re*d,im*d);}
double re,im;

};However when multiplying double * CComplex the operation fails

double m_Phase[8192][8192]; // Phase of Field
double m_Amplitude[8192][8192]; // Amplitude of Field
CComplex m_Field[8192][8192]; // Full electric Field

CComplex Expi(double wt) {return CComplex(cos(wt),sin(wt));}
CComplex Expi(CComplex x) {return

m_Field[x][y]= (m_Amplitude[x][y]) * (Expi(m_Phase[x][y]));

with

error C2677: Binärer Operator '*': Es konnte kein globaler Operator
gefunden werden, der den Typ 'CComplex' akzeptiert (oder keine geeignete
Konvertierung möglich)

You have defined an operator* for CComplex * double, but not for double
* CComplex. I'm not sure what the solution to this problem is, it might
have something to do with not declaring the operator as a member. I
seem to recall that there is something about it in the FAQ though,
check it out: http://www.parashift.com/c++-faq-lite/.

Aslo, why do you create a complex-class when there already exist on in
the standard library?
 
D

dasjotre

Matthias said:
I have a Class for complex operations:

what is wrong with std::complex ?
class CComplex
{
public:
inline CComplex() { re=im=0.0; }

use constructor initializer list for member initialization wherever
possible

CComplex() : re(0), im(0) {}
inline CComplex operator*(CComplex c) { return

since it returns new object by value, then it doesn't modify nither
'this' nor c, why is it not

CComplex operator*(CComplex const & c) const

then.

I believe that the general rule for operator is to make +=, -=, *= and
/= members
and all others to declare outside the class.

CComplex & operator*=(CComplex const & c)
{
...
return *this;
}
CComplex(re*c.re-im*c.im,re*c.im+im*c.re);}

there is no CComplex constructor that takes two doubles
inline CComplex operator*(double &d) { return CComplex(re*d,im*d);}

you pass double by reference and objects by value, why?
double re,im;

consider declaring each member on it's own line

you need to define a double*CComplex binary operator *

CComplex operator*(double d, CComplex const & c)
 
M

Matthias Pospiech

dasjotre said:
you pass double by reference and objects by value, why?
what do you mean by 'objects by value' ?
you need to define a double*CComplex binary operator *

CComplex operator*(double d, CComplex const & c)
I do not know how to implement such a function. The following does not work

CComplex operator*(double d, CComplex const & c) { return
CComplex(c.re*d,c.im*d);}
>[...].h(102) : error C2804: Binärer Operator '*' hat zu viele Parameter
>[...].h(102) : error C2333: 'CComplex::eek:perator *': Fehler in
Funktionsdeklaration; Funktionstext wird übersprungen

I think some working example code would be helpfull.

Matthias
 
D

dasjotre

Matthias Pospiech wrote:
<snip>

class CComplex
{
public:

CComplex(): re(0), im(0) {}
CComplex(double d, double c): re(d), im(c) {}
// you don't realy need to define this, but it will
// help you understand the distinction between
// by-value and by-reference
CComplex(CComplex const & cpy)
: re(cpy.re), im(cpy.im)
{
}
CComplex & operator *=(CComplex const & c)
{
re = re*c.re-im*c.im;
im = re*c.im+im*c.re;
return *this;
}
CComplex & operator*=(double d)
{
re *= d;
im *= d;
return *this;
}

private:

double re;
double im;
};
// binary operators outside the class
inline CComplex operator*(double d, CComplex const & c)
{
CComplex ret(c);
ret *= d;
return ret;
}
inline CComplex operator*(CComplex const & c, double d)
{
return (d*c);
}

// try these
void CComplex_passed_by_value(CComplex c){}
void CComplex_passed_by_reference(CComplex & c){}

I think some working example code would be helpfull.

yes, a compilable code at least. take that as a basic requirement next
time you post here ;)
 
M

Matthias Pospiech

dasjotre said:
yes, a compilable code at least. take that as a basic requirement next
time you post here ;)
It does compile.

However, I have never seen the following construct before:

CComplex(): re(0), im(0) {}

I do understand what it does, but is there any documentation about this
syntax on the web that I can read ?

Matthias
 
M

Marcus Kwok

Matthias Pospiech said:
However, I have never seen the following construct before:

CComplex(): re(0), im(0) {}

I do understand what it does, but is there any documentation about this
syntax on the web that I can read ?

Try searching for something like "initializer list" or "initialization
list". If you have a reference or a const member in your class, it is
the only way to initialize them, and if you have a derived class, it is
used to call a base class constructor if you need to pass a parameter to
it.
 
M

Matthias Pospiech

The Code based on your post (see bottom of this post) compiles and
works. However other previous working code now fails - and I do not
understand why...

The following class (with #include <MpMath.h>)

class CComplexVector2
{
public:
/* Konstruktoren */
inline CComplexVector2() { m[1]=&x;m[2]=&y; x.re=y.re=x.im=y.im=0.0; }
inline CComplexVector2(const CComplexVector2 &c) { m[1]=&x;m[2]=&y;
x=c.x;y=c.y;}
inline CComplexVector2(const double &d1, const double &d2) {
m[1]=&x;m[2]=&y; x.re=d1;y.re=d2;x.im=y.im=0.0;}
inline CComplexVector2(const CComplex &d1, const CComplex &d2) {
m[1]=&x;m[2]=&y; x=d1;y=d2;}
/* Operatoren */
inline CComplexVector2& operator=(const CComplexVector2 &c) {
m[1]=&x;m[2]=&y; x=c.x;y=c.y; return *this;}
inline CComplexVector2 operator+(CComplexVector2 c) { return
CComplexVector2(x+c.x,y+c.y);}
inline CComplexVector2 operator+(CVector2 c) { return
CComplexVector2(x+c.x,y+c.y);}
CComplex x,y;
CComplex *m[3];
};



fails with
>D:\Matthias\CPP\Uwe\C++\LightModulator2D\LightModulator2D\um.h(185) :
error C2678: Binärer Operator '+': Es konnte kein Operator gefunden
werden, der einen linksseitigen Operanden vom Typ 'CComplex' akzeptiert
(oder keine geeignete Konvertierung möglich)
1>
D:\Matthias\CPP\Uwe\C++\LightModulator2D\LightModulator2D\MpMath.h(51):
kann 'CComplex operator +(double,const CComplex &)' sein
1>
D:\Matthias\CPP\Uwe\C++\LightModulator2D\LightModulator2D\MpMath.h(52):
oder "CComplex operator +(const CComplex &,double)"
1> bei Anpassung der Argumentliste '(CComplex, CComplex)'


The CComplex class now looks like (MpMath.cpp)


class CComplex
{
public:
/* Überladen Konstruktoren */
CComplex(): re(0), im(0) {}
//CComplex(const double &d, const double &c): re(d), im(c) {}
CComplex(const double &d1, const double &d2) {re=d1;im=d2;}
CComplex(const CComplex &c) { re=c.re;im=c.im;}
CComplex(const double &c) { re=c;im=0.0;}

/* Multiplikation */
CComplex & operator *=(CComplex const & c){re = re*c.re-im*c.im; im =
re*c.im+im*c.re; return *this;}
CComplex & operator *=(double d) {re *= d;im *= d; return *this;}
/* Addition */
CComplex & operator +=(CComplex const &c) {re=re+c.re; im=im+c.im;
return *this;}
CComplex & operator +=(double d) {re+=d; return *this;}
/* Subtraction */
CComplex & operator -=(CComplex const &c) {re= re-c.re; im=im-c.im;
return *this;}
CComplex & operator -=(double d) {re-=d; return *this;}
/* Division */
CComplex & operator /=(CComplex const &c) {
double b=c.re*c.re+c.im*c.im;
re=(re*c.re+im*c.im)/b;im=(im*c.re-re*c.im)/b; return *this;
};
CComplex & operator /=(double d){re=re/d;im=im/d;return *this;}
/* Invers */
CComplex operator -() { return CComplex(-re,-im);}
public:
double re;
double im;
};

// binary operators outside the class
// Necessary to have double * complex AND complex * double
inline CComplex operator*(double d, CComplex const & c){CComplex
ret(c);ret *= d;return ret;}
inline CComplex operator*(CComplex const & c, double d){return (d*c);}
inline CComplex operator+(double d, CComplex const & c){CComplex
ret(c);ret += d;return ret;}
inline CComplex operator+(CComplex const & c, double d){return (d+c);}
inline CComplex operator-(double d, CComplex const & c){CComplex
ret(c);ret -= d;return ret;}
inline CComplex operator-(CComplex const & c, double d){return (d-c);}
inline CComplex operator/(double d, CComplex const & c){CComplex
ret(c);ret /= d;return ret;}
inline CComplex operator/(CComplex const & c, double d){return (d/c);}
 
B

Bernd Strieder

Hello,

Matthias said:
The Code based on your post (see bottom of this post) compiles and
works. However other previous working code now fails - and I do not
understand why...

Because now some overloads of operator* and others are missing, esp. the
operator* for two CComplex objects. There is no automatism in C++ to
provide e.g. operator*(CComplex,CComplex) from
CComplex::eek:perator*=(CComplex)
class CComplex
{
...
public:
double re;
double im;
};

// binary operators outside the class
// Necessary to have double * complex AND complex * double
inline CComplex operator*(double d, CComplex const & c){CComplex
ret(c);ret *= d;return ret;}
inline CComplex operator*(CComplex const & c, double d){return (d*c);}

The following overload is plainly missing, analogously for other
operators. You might even get away with this missing one alone, since a
double can be converted via implicit constructor to CComplex. Due to
inlining all modern compilers should produce equivalent results here.
So it might be recommendable to provide only this one overload, and
rely on conversion for the others:

inline CComplex operator*(CComplex const & c, CComplex const & d)
{
CComplex z(c);
z*=d;
return z;
}

Now you might be tempted to move this operator back into the class as
member function, but then it will fail again to provide all usually
wanted overloads. For member functions to match the left hand side of
the operator must be of the class, there are no conversions considered.

Bernd Strieder
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top