446,389 Members | 1,795 Online
Need help? Post your question and get tips & solutions from a community of 446,389 IT Pros & Developers. It's quick & easy.

 P: n/a I've been working on creating a Complex class for my own learning purpose (learn through doing etc.). I'm once again puzzled about something. I can't figure out how to overload the assignment operator. Here's what I'm trying to do. I've defined class Complex as class Complex { friend ostream &operator<<( ostream &, Complex & ); public: Complex( float = 0.0, float = 0.0 ); Complex operator+( Complex & ); Complex operator-( Complex & ); Complex operator*( Complex & ); Complex operator/( Complex & ); Complex operator=( Complex & ); Complex conjugate(); float magnitude(); private: float re; float im; }; The constructor is Complex::Complex( float a, float b ) : re( a ), im( b ) { } I have no idea how to write the overload function though. This doesn't work Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } Help!!!! :-) Thanks in advance! Pmb Jul 22 '05 #1
34 Replies

 P: n/a * "Pmb" schriebt: I have no idea how to write the overload function though. This doesn't work Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } Help!!!! :-) Should the "=" operation ever _change_ the value that is on the right hand side of '='? No? In that case, it should be 'const'. Should you ever be able to write e.g. a = b = Complex( 1, 2 ); ? Yes? In that case, the return value should be a reference so that it can be modified (e.g., in turn invoking '=' on the result). -- A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? Jul 22 '05 #2

 P: n/a "Alf P. Steinbach" wrote in message news:40****************@news.individual.net... * "Pmb" schriebt: I have no idea how to write the overload function though. This doesn't work Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } Help!!!! :-) Should the "=" operation ever _change_ the value that is on the right hand side of '='? No? In that case, it should be 'const'. I'm not interested in worrying about const and program integrity at this point. This code will never be used. This particular program is simply for me to learn about writing overload functions for operators. Should you ever be able to write e.g. a = b = Complex( 1, 2 ); ? Yes? In that case, the return value should be a reference so that it can be modified (e.g., in turn invoking '=' on the result). Do you mean something like Complex &operator=( Complex & ); Complex &Complex::operator=( Complex &z ) { return this; } I still don't see what to place in the body to do the work. Suppose class Complex { friend ostream &operator<<( ostream &, Complex & ); public: Complex( float = 0.0, float = 0.0 ); Complex operator+( Complex & ); Complex operator-( Complex & ); Complex operator*( Complex & ); Complex operator/( Complex & ); Complex &operator=( Complex & ); Complex conjugate(); float magnitude(); private: float re; float im; }; It would seem to me that the operator function would be Complex &Complex::operator=( Complex &z ) { re = z.re; im = z.im; return this; } But this doesn't work. Pmb Jul 22 '05 #3

 P: n/a * "Pmb" schriebt: "Alf P. Steinbach" wrote in message news:40****************@news.individual.net... * "Pmb" schriebt: I have no idea how to write the overload function though. This doesn't work Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } Help!!!! :-) Should the "=" operation ever _change_ the value that is on the right hand side of '='? No? In that case, it should be 'const'. I'm not interested in worrying about const and program integrity at this point. This code will never be used. This particular program is simply for me to learn about writing overload functions for operators. You will not learn about overloading in C++ if you refuse to consider 'const'. Should you ever be able to write e.g. a = b = Complex( 1, 2 ); ? Yes? In that case, the return value should be a reference so that it can be modified (e.g., in turn invoking '=' on the result). Do you mean something like Complex &operator=( Complex & ); Complex &Complex::operator=( Complex &z ) { return this; } I still don't see what to place in the body to do the work. Suppose class Complex { friend ostream &operator<<( ostream &, Complex & ); public: Complex( float = 0.0, float = 0.0 ); Complex operator+( Complex & ); Complex operator-( Complex & ); Complex operator*( Complex & ); Complex operator/( Complex & ); Complex &operator=( Complex & ); Complex conjugate(); float magnitude(); private: float re; float im; }; It would seem to me that the operator function would be Complex &Complex::operator=( Complex &z ) { re = z.re; im = z.im; return this; } But this doesn't work. Say rather, it does not _compile_. First make it compile. -- A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? Jul 22 '05 #4

 P: n/a Pmb wrote in news:YJ********************@comcast.com in comp.lang.c++: I've been working on creating a Complex class for my own learning purpose (learn through doing etc.). I'm once again puzzled about something. I can't figure out how to overload the assignment operator. You're not overloading anything here, you're *declaring* and then *defining* Complex::operator = ( Complex & ); Here's what I'm trying to do. I've defined class Complex as #include /* always try to make your examples compile */ class Complex { friend ostream &operator<<( ostream &, Complex & ); friend std::ostream &operator<<( std::ostream &, Complex & ); When I compiled your code the above was the only error I found. public: Complex( float = 0.0, float = 0.0 ); Complex operator+( Complex & ); Complex operator-( Complex & ); Complex operator*( Complex & ); Complex operator/( Complex & ); All of the above *create* a new value, so its appropriate that they return by value. Complex operator=( Complex & ); The above dose *not* create a new value, but modifies the 'this' object, logicaly it should return Complex &. Also it doesn't modify is argument, so you should prefer Complex const &. As well as being "const correct" this will allow you to later write code like: Complex a( 1, 2 ), b( 2, 3 ); a = b.conjugate(); or: a = a + b; As the tempraries returned by + and .conjugate() can't be passed to a function that takes a non-const reference. Complex conjugate(); float magnitude(); private: float re; float im; }; The constructor is Complex::Complex( float a, float b ) : re( a ), im( b ) { } I have no idea how to write the overload function though. This doesn't work Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } What doesn't work about it, with the 'ostream' issue above fixed it compiles fine for me. Are you sure the error your seeing isn't coming from elswhere ? Rob. -- http://www.victim-prime.dsl.pipex.com/ Jul 22 '05 #5

 P: n/a > > I'm not interested in worrying about const and program integrity at this point. This code will never be used. This particular program is simply for me to learn about writing overload functions for operators. You will not learn about overloading in C++ if you refuse to consider 'const'. It's worse than that. With certain compilers you will learn illegal C++. If you then switch to a compiler that enforces const correctness you will have to relearn C++ that you thought you already knew. Pmb, its not so hard Complex operator+( const Complex & ) const; Complex& operator=( const Complex & ); john Jul 22 '05 #6

 P: n/a "Alf P. Steinbach" wrote in message news:40****************@news.individual.net... * "Pmb" schriebt: "Alf P. Steinbach" wrote in message news:40****************@news.individual.net... * "Pmb" schriebt: > I have no idea how to write the overload function though. This doesn't work > > Complex Complex::operator=( Complex &z ) > { > re = z.re; > im = z.im; > > return *this; > } > > > Help!!!! :-) Should the "=" operation ever _change_ the value that is on the right hand side of '='? No? In that case, it should be 'const'. I'm not interested in worrying about const and program integrity at this point. This code will never be used. This particular program is simply for me to learn about writing overload functions for operators. You will not learn about overloading in C++ if you refuse to consider 'const'. I didn't say that I refuse to consider const pmb Jul 22 '05 #7

 P: n/a "John Harrison" wrote in message news:2h************@uni-berlin.de... I'm not interested in worrying about const and program integrity at this point. This code will never be used. This particular program is simply for me to learn about writing overload functions for operators. You will not learn about overloading in C++ if you refuse to consider 'const'. It's worse than that. With certain compilers you will learn illegal C++. If you then switch to a compiler that enforces const correctness you will have to relearn C++ that you thought you already knew. I think you both read something into what I said that wasn't there. I said *at this point*. When I learn a new language and try examples I make them as simple as possible and work my way up. After I got this to compile and got the logic correct, I was going to go back and place in the const.'s. Pmb, its not so hard Complex operator+( const Complex & ) const; Complex& operator=( const Complex & ); Still doesn't work. However I'm not sure where the error is. thanks Pmb Jul 22 '05 #8

 P: n/a "Rob Williscroft" wrote What doesn't work about it, with the 'ostream' issue above fixed it compiles fine for me. Are you sure the error your seeing isn't coming from elswhere ? There wasn't an "ostream" issue. I simply didn't post the entire code. I suppose I should have in retrospect. The following is the compile error I get from the program below ----------------- Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland d:\temp\test\example.cpp: Error E2285 d:\temp\test\example.cpp 130: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 138: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 139: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 140: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 141: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 148: Could not find a match for 'Complex::operator =(Complex)' in function main() *** 6 errors in Compile *** Tool completed with exit code 1 ------------------ Line 130 is " uConj = u.conjugate();" Lines 138-141 are 138 "sum = u + v;" 139 "diff = u - v;" 140 "prod = u*v;" 141 "ratio = u/v;" What am I doing wrong this time? Thanks Pmb _____________________________________________ #include #include class Complex { friend ostream &operator<<( ostream &, Complex & ); public: Complex( float = 0.0, float = 0.0 ); Complex operator+( Complex & ); Complex operator-( Complex & ); Complex operator*( Complex & ); Complex operator/( Complex & ); Complex operator=( Complex & ); private: float re; float im; }; ostream &operator<<( ostream &output, Complex &z ) { float x = z.re, y = z.im; if ( y == 0 ) // z = a output << x; else if ( x == 0 && y > 0 ) // z = i b output << "i " << y; else if ( x == 0 && y < 0 ) // z = - i b output << "- i " << -y; else if ( x > 0 && y > 0 ) // z = a + i b output << x << " + i " << z.im; else if ( x > 0 && y < 0 ) // z = a - i b output << x << " - i " << -y; else if ( x < 0 && y < 0 ) // z = -a - i b output << x << " - i " << -y; else if ( x < 0 && y > 0 ) // z = -a + i b output << x << " + i " << y; return output; } Complex::Complex( float a, float b ) : re( a ), im( b) { } Complex Complex::operator+( Complex &z ) { return Complex( re + z.re, im + z.im ); } Complex Complex::operator-( Complex &z ) { return Complex( re - z.re, im - z.im ); } Complex Complex::operator*( Complex &z ) { // z1 = x1 + i y1, z2 = x2 + i y2 // // z1*z2 = ( x1 + i y1 )*( x2 + i y2 ) // = ( x1*x2 + i x1*y2 + i x2*y1 - y1*y2 // = ( x1*x2 - y1*y2 ) + i ( x1*y2 + x2*y1 ) float x1 = re, y1 = im, x2 = z.re , y2 = z.im; return Complex( x1*x2 - y1*y2, x1*y2 + x2*y1 ); } Complex Complex::operator/( Complex &z ) { // z1 = x1 + i y1, z2 = x2 + i y2 // // z1 z1 z2* z1*z2 z1*z2 // -- = -- -- = ------ = ------------- // z2 z2 z2* |z2|^2 x1*x1 + y1*y1 // // z1*z2 = ( x1*x2 - y1*y2 ) + i ( x1*y2 + x2*y1 ) // // z1 x1*x2 - y1*y2 x1*y2 + x2*y1 // -- = ----------------- + i ------------- // z2 x1*x1 + y1*y1 x1*x1 + y1*y1 // // a = x1*x2 - y1*y2, b = x1*y2 + x2*y1, c = x1*x1 + y1*y1 // // z1 a b // -- = -- + i -- = x + i y // z2 c c // // x = a/c, y = b/c // float x1 = re, y1 = im, x2 = z.re , y2 = z.im; float a, b, c, x, y; a = x1*x2 - y1*y2; b = x1*y2 + x2*y1; c = x1*x1 + y1*y1; x = a/c; y = b/c; return Complex( x, y ); } Complex Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } Complex Complex::conjugate() { return Complex( re, -im); } float Complex::magnitude() { return sqrt( re*re + im*im ); } int main() { Complex u( 1, 5 ), v( 2, 2 ), w( 1, 1 ); Complex uConj, sum, prod, diff, ratio; float r; uConj = u.conjugate(); r = u.magnitude(); cout << "\nu = " << u << endl; cout << "\nv = " << v << endl; cout << "\nu* = " << uConj << endl; cout << "\n|u| = " << r << endl; sum = u + v; diff = u - v; prod = u*v; ratio = u/v; cout << "\nu + v = " << sum << endl; cout << "\nu - v = " << diff << endl; cout << "\nu*v = " << prod << endl; cout << "\nu/v = " << ratio << endl; sum = u + v + w; cout << "\nu + v + w = " << sum << endl; return 0; } _____________________________________________ Jul 22 '05 #9

 P: n/a "Pmb" wrote in message news:Xs********************@comcast.com... "Rob Williscroft" wrote What doesn't work about it, with the 'ostream' issue above fixed it compiles fine for me. Are you sure the error your seeing isn't coming from elswhere ? There wasn't an "ostream" issue. I simply didn't post the entire code. I suppose I should have in retrospect. The following is the compile error I get from the program below ----------------- Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland d:\temp\test\example.cpp: Error E2285 d:\temp\test\example.cpp 130: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 138: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 139: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 140: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 141: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 148: Could not find a match for 'Complex::operator =(Complex)' in function main() *** 6 errors in Compile *** Tool completed with exit code 1 ------------------ Line 130 is " uConj = u.conjugate();" Lines 138-141 are 138 "sum = u + v;" 139 "diff = u - v;" 140 "prod = u*v;" 141 "ratio = u/v;" What am I doing wrong this time? Forgetting const, put the const in and it will compile. Complex& operator=(const Complex & ); What you are failing to realise is that you cannot bind a temporary to a non-const reference. sum = u + v; u + v returns a temporary, you have declared your operator= with a non-const reference. Therefore you cannot use u + v on the right hand side of a operator=. Just add const. john Jul 22 '05 #10

 P: n/a "John Harrison" wrote in message news:2h************@uni-berlin.de... "Pmb" wrote in message news:Xs********************@comcast.com... "Rob Williscroft" wrote What doesn't work about it, with the 'ostream' issue above fixed it compiles fine for me. Are you sure the error your seeing isn't coming from elswhere ? There wasn't an "ostream" issue. I simply didn't post the entire code. I suppose I should have in retrospect. The following is the compile error I get from the program below ----------------- Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland d:\temp\test\example.cpp: Error E2285 d:\temp\test\example.cpp 130: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 138: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 139: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 140: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 141: Could not find a match for 'Complex::operator =(Complex)' in function main() Error E2285 d:\temp\test\example.cpp 148: Could not find a match for 'Complex::operator =(Complex)' in function main() *** 6 errors in Compile *** Tool completed with exit code 1 ------------------ Line 130 is " uConj = u.conjugate();" Lines 138-141 are 138 "sum = u + v;" 139 "diff = u - v;" 140 "prod = u*v;" 141 "ratio = u/v;" What am I doing wrong this time? Forgetting const, put the const in and it will compile. Complex& operator=(const Complex & ); What you are failing to realise is that you cannot bind a temporary to a non-const reference. I see no reason for that to be true. sum = u + v; u + v returns a temporary, you have declared your operator= with a non-const reference. Therefore you cannot use u + v on the right hand side of a operator=. Just add const. I disagree. I simplified the code I'm working on to the bare bones. It now reads _______________________________________ #include class Complex { public: Complex( float = 0.0, float = 0.0 ); Complex &operator=( Complex & ); float getRe() { return re; }; float getIm() { return im; }; private: float re; float im; }; Complex::Complex( float a, float b ) : re( a ), im( b) { } Complex& Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } int main() { Complex z1( 1, 5 ), z2( 0, 0 ); float x, y; x = z2.getRe(); y = z2.getIm(); cout << "Components before 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; z2 = z1; x = z2.getRe(); y = z2.getIm(); cout << "\nComponents after 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; return 0; } _______________________________________ This program works just fine. The output is ------------ Components before 'operator=' call: (x,y) = (0,0) Components after 'operator=' call: (x,y) = (1,5) ------------ That is exactly what I want it to do. Had I wanted to use this code further then perhaps I'd used const's. Not while I'm in a learning mode. When learning one seeks to understand when something is required and when it is not required and how it affects the logic etc. Perhaps everyone disagrees with the way I chose to learn. But that is the way I choose to learn Pmb Jul 22 '05 #11

 P: n/a > > Forgetting const, put the const in and it will compile. Complex& operator=(const Complex & ); What you are failing to realise is that you cannot bind a temporary to a non-const reference. I see no reason for that to be true. You might not see a reason, other people don't see the reason, its somewhat controversial, but its in the C++ standard in black and white. However some compilers do not enforce that rule. sum = u + v; u + v returns a temporary, you have declared your operator= with a non-const reference. Therefore you cannot use u + v on the right hand side of a operator=. Just add const. I disagree. I simplified the code I'm working on to the bare bones. It now reads Fine but you've changed the program to avoid the problem I described. You no longer have a temporary on the rhs of an assignment. _______________________________________ #include class Complex { public: Complex( float = 0.0, float = 0.0 ); Complex &operator=( Complex & ); float getRe() { return re; }; float getIm() { return im; }; private: float re; float im; }; Complex::Complex( float a, float b ) : re( a ), im( b) { } Complex& Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } int main() { Complex z1( 1, 5 ), z2( 0, 0 ); float x, y; x = z2.getRe(); y = z2.getIm(); cout << "Components before 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; z2 = z1; x = z2.getRe(); y = z2.getIm(); cout << "\nComponents after 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; return 0; } _______________________________________ This program works just fine. The output is ------------ Components before 'operator=' call: (x,y) = (0,0) Components after 'operator=' call: (x,y) = (1,5) ------------ That is exactly what I want it to do. Had I wanted to use this code further then perhaps I'd used const's. Not while I'm in a learning mode. When learning one seeks to understand when something is required and when it is not required and how it affects the logic etc. Perhaps everyone disagrees with the way I chose to learn. But that is the way I choose to learn I was just answering the question you asked, 'What have I done wrong this time?' I pointed out a way (the only way) to make your program compile, you chose to write a different program instead. john Jul 22 '05 #12

 P: n/a "John Harrison" wrote in message news:2h************@uni-berlin.de... Forgetting const, put the const in and it will compile. Complex& operator=(const Complex & ); What you are failing to realise is that you cannot bind a temporary to a non-const reference. I see no reason for that to be true. You might not see a reason, other people don't see the reason, its somewhat controversial, but its in the C++ standard in black and white. However some compilers do not enforce that rule. sum = u + v; u + v returns a temporary, you have declared your operator= with a non-const reference. Therefore you cannot use u + v on the right hand side of a operator=. Just add const. I disagree. I simplified the code I'm working on to the bare bones. It now reads Fine but you've changed the program to avoid the problem I described. You no longer have a temporary on the rhs of an assignment. _______________________________________ #include class Complex { public: Complex( float = 0.0, float = 0.0 ); Complex &operator=( Complex & ); float getRe() { return re; }; float getIm() { return im; }; private: float re; float im; }; Complex::Complex( float a, float b ) : re( a ), im( b) { } Complex& Complex::operator=( Complex &z ) { re = z.re; im = z.im; return *this; } int main() { Complex z1( 1, 5 ), z2( 0, 0 ); float x, y; x = z2.getRe(); y = z2.getIm(); cout << "Components before 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; z2 = z1; x = z2.getRe(); y = z2.getIm(); cout << "\nComponents after 'operator=' call: (x,y) = (" << x << "," << y << ")" << endl; return 0; } _______________________________________ This program works just fine. The output is ------------ Components before 'operator=' call: (x,y) = (0,0) Components after 'operator=' call: (x,y) = (1,5) ------------ That is exactly what I want it to do. Had I wanted to use this code further then perhaps I'd used const's. Not while I'm in a learning mode. When learning one seeks to understand when something is required and when it is not required and how it affects the logic etc. Perhaps everyone disagrees with the way I chose to learn. But that is the way I choose to learn I was just answering the question you asked, 'What have I done wrong this time?' I pointed out a way (the only way) to make your program compile, you chose to write a different program instead. I think I see what you're saying. This is why I left the const's out - learning purposes. If what you say is true (and I now see that perhaps it is) then I would have missed this point had I put them in solely for the purpose of good programming practice. Now I know that there are circumstances where leaving the const out causes compile errors. Thanks Pmb Jul 22 '05 #13

 P: n/a > I think I see what you're saying. This is why I left the const's out - learning purposes. If what you say is true (and I now see that perhaps it is) then I would have missed this point had I put them in solely for the purpose of good programming practice. Now I know that there are circumstances where leaving the const out causes compile errors. Thanks Pmb In C there's a notion which says that any legal program that uses const would also be a legal program if all the consts were removed. That has never been true in C++. john Jul 22 '05 #14

 P: n/a "John Harrison" wrote in message news:2h************@uni-berlin.de... I think I see what you're saying. This is why I left the const's out - learning purposes. If what you say is true (and I now see that perhaps it is) then I would have missed this point had I put them in solely for the purpose of good programming practice. Now I know that there are circumstances where leaving the const out causes compile errors. Thanks Pmb In C there's a notion which says that any legal program that uses const would also be a legal program if all the consts were removed. That has never been true in C++. What does the C++ standard say on this issue? Pmb Jul 22 '05 #15

 P: n/a ----- Original Message ----- From: "John Harrison" Newsgroups: comp.lang.c++ Sent: Saturday, May 29, 2004 7:50 AM Subject: Re: Overloading the "=" operator for Complex numbers I think I see what you're saying. This is why I left the const's out - learning purposes. If what you say is true (and I now see that perhaps it is) then I would have missed this point had I put them in solely for the purpose of good programming practice. Now I know that there are circumstances where leaving the const out causes compile errors. Thanks Pmb In C there's a notion which says that any legal program that uses const would also be a legal program if all the consts were removed. That has never been true in C++. While I now understand that I *must* put const in I still don't understand *why* I must do that? You wrote What you are failing to realise is that you cannot bind a temporary to a non-const reference. What does "bind a temporary" mean? sum = u + v; u + v returns a temporary, ... Please clarify. What do you mean by "returns a temporary"? I assume that you're referring to the return value of Complex Complex::operator+( Complex &z ) Since this is a temporary and since this is what goes into the input of Complex& Complex::operator=( const Complex &z ) Then shouldn't the input be temporary? ...you have declared your operator= with a non-const reference. Doesn't "non-constant" mean "temporary"? Thanks Pmb ps - Sorry. I accidently sent this to your e-mail too Jul 22 '05 #16

 P: n/a Pmb posted: While I now understand that I *must* put const in I still don't understand *why* I must do that? int a = 6; const int b = 5; const int c = 4; a = b; Self explanatory I hope. What you are failing to realise is that you cannot bind a temporary to a non-const reference. What does "bind a temporary" mean? sum = u + v; u + v returns a temporary, ... Please clarify. What do you mean by "returns a temporary"? unsigned int GiveNumber(void) { return 27; } int main(void) { int& given_number = GiveNumber(); given_number = 27; //Guess what happens here... //The object returned from GiveNumber no longer exists, I have //a hanging pointer, in the form of a reference. And I just accessed //"unallocated" memory, memory that ain't mine. BOLD! } Jul 22 '05 #17

 P: n/a Hi Pmb, ( and all you C++ guys too ) [ Posted & e-mailed ] You showed, " sum = u + v; ". And in your e-mail to me you showed: cin >> "Enter z = x + i y: " >> z; I'd be nice if one could say: cin >> "Enter z, ( in the form: Real + Imaginary ): " >> z; Then the user could simply type in something like: 5 + 6 But you can't overload the + symbol like that, because it reacts to the type of the operands, which, in this case, are not even reals, much less complex. ( They are integers ) Could that be solved by using something other than the + symbol ? Correct me if I'm wrong here C++ guys, but I think the only solution is to use string input like this: float Real; String A_String_Operator; float Imaginary; cin >> "Enter z," " ( in the form: Real + Imaginary, " " spaces required ): " >> Real >> A_String_Operator >> Imaginary; Then the user could simply type in something like: 5 + 6 Jul 22 '05 #18

 P: n/a "Pmb" wrote in message news:dI********************@comcast.com ----- Original Message ----- From: "John Harrison" While I now understand that I *must* put const in I still don't understand *why* I must do that? You wrote What you are failing to realise is that you cannot bind a temporary to a non-const reference. What does "bind a temporary" mean? A reference refers to an object. A reference is "bound to a temporary" when it is made to refer to a temporary. The binding takes place in this instance when the temporary is passed as the operator argument. sum = u + v; u + v returns a temporary, ... Please clarify. What do you mean by "returns a temporary"? I assume that you're referring to the return value of Complex Complex::operator+( Complex &z ) Correct. Since this is a temporary and since this is what goes into the input of Complex& Complex::operator=( const Complex &z ) Then shouldn't the input be temporary? Yes, the input is a temporary. But the reference is a const reference. You are allowed to bind temporaries to const references, but not to non-const references. Doesn't "non-constant" mean "temporary"? No. const and non-const has to do with the right to modify an object. When you declare an operator with Complex& Complex::operator=(Complex &z ); the operator has the right to modify whatever is passed in as its argument. Thus the assignment in z = u; would allow u to be modified by the assignment operator. By contrast, a declaration of Complex& Complex::operator=( const Complex &z ); means that the assignment operator is not allowed to modify its argument (u in the above example). Why is only the second version allowed when the argument is a temporary? This is to prevent programmers from making a particular type of error. If a function or operator modifies its argument, then that usually means that the programmer wishes to change the object in the scope from which the function or operator has been called, as in the following example: void DoubleValue(int &n) { n *=2; } int main() { int m = 2; DoubleValue(m); // m will now be 4 } Now if the argument passed to a function is a temporary, then the function's action will change the value of the temporary, but the temporary will cease to exist as soon as the function returns. Thus the function will not have an effect in the scope from which it is called. This may be an unpleasant surprise to the programmer, so the language prevents the passing of temporaries to functions and operators with non-const reference parameters in order to eliminate the possibility of this unpleasant surprise. The risk of this surprise is greater than you might think because temporaries get generated in more cases than you might think. -- John Carson 1. To reply to email address, remove donald 2. Don't reply to email address (post here instead) Jul 22 '05 #19

 P: n/a "Pmb" wrote in message news:dI********************@comcast.com... ----- Original Message ----- From: "John Harrison" Newsgroups: comp.lang.c++ Sent: Saturday, May 29, 2004 7:50 AM Subject: Re: Overloading the "=" operator for Complex numbers I think I see what you're saying. This is why I left the const's out - learning purposes. If what you say is true (and I now see that perhaps it is) then I would have missed this point had I put them in solely for the purpose of good programming practice. Now I know that there are circumstances where leaving the const out causes compile errors. Thanks Pmb In C there's a notion which says that any legal program that uses const would also be a legal program if all the consts were removed. That has never been true in C++. While I now understand that I *must* put const in I still don't understand *why* I must do that? You wrote What you are failing to realise is that you cannot bind a temporary to a non-const reference. What does "bind a temporary" mean? sum = u + v; u + v returns a temporary, ... Please clarify. What do you mean by "returns a temporary"? I assume that you're referring to the return value of Complex Complex::operator+( Complex &z ) Since this is a temporary and since this is what goes into the input of Complex& Complex::operator=( const Complex &z ) Then shouldn't the input be temporary? ...you have declared your operator= with a non-const reference. Doesn't "non-constant" mean "temporary"? Thanks Pmb A temporary is an unnamed object. 'u + v' returns a Complex object, but that object has no name, so it's a temporary (the compiler creates it when the functions returns and destroys it when it been used, hence its called a temporary). Any function or operator that returns an object returns a temporary. There are various other ways to create temporaries class X { public: X(int x); }; void f(const X& x); f(1); There's a constructor for X that takes an int, so when you try to call f using an int, the compiler creates a temporary X from the int and uses that to call f. You can also create temporaries explicitly Complex z = Complex(1.0, 2.0) + Complex(3.0, 4.0); The objects created by Complex(1.0, 2.0) and Complex(3.0, 4.0) have no name, they are temporaries. When a reference is initialised its usually referred to as binding a reference. int x; int& y = x; // y is bound to x Now the crunch, a temporary cannot be bound to a non-const reference. Suppose you have written class Complex { public: Complex operator+(Complex& rhs); Now this is illegal Complex z = Complex(1.0, 2.0) + Complex(3.0, 4.0); The right hand side of your operator+ is a temporary but you operator+ has been written with a non-const reference, so the above should not compile. Similarly Complex f(); Complex z = Complex(1.0, 2.0) + f(); Again the right hand side is a temporary. Why does C++ have this rule? That's a good question, Bjarne Stroustrup says that it leads to code that is too confusing, he has in mind code like this void trim_whitespace(string& s); // removes whitespace from s trim_whitespace(" abc "); Without the 'can't bind a temporary to a non-const reference' rule the compiler would create a temporary string from " abc ", that would be passed to trim_whitespace, which would faithfully remove the whitespace, but when the function returns the temporary (with its whitespace removed) would be destroyed. The original string literal " abc " would be completely untouched. With the rule the above will not compile, which it what you would want. As I said this isn't uncontroversial, but it is the way C++ is. If you want to consult the standard 8.5.3 para 5 john Jul 22 '05 #20

 P: n/a Jeff Relf wrote: Hi Pmb, ( and all you C++ guys too ) [ Posted & e-mailed ] You showed, " sum = u + v; ". And in your e-mail to me you showed: cin >> "Enter z = x + i y: " >> z; Whoever wrote that is leading you astray. 'cin' is not some kind of magic prompt system. The string literal will turn to a constant char pointer, which won't compile. Try cout << "Enter z = x + i y: "; std::string zee; std::getline(cin, zee); That interprets linefeeds as turnaround characters. But then you must parse zee and get the integer out of it. I'd be nice if one could say: cin >> "Enter z, ( in the form: Real + Imaginary ): " >> z; Then the user could simply type in something like: 5 + 6 But you can't overload the + symbol like that, because it reacts to the type of the operands, which, in this case, are not even reals, much less complex. ( They are integers ) The user can't type + unless you parse it. If you do, you get to decree what it does. Could that be solved by using something other than the + symbol ? Correct me if I'm wrong here C++ guys, but I think the only solution is to use string input like this: float Real; String A_String_Operator; float Imaginary; cin >> "Enter z," " ( in the form: Real + Imaginary, " " spaces required ): " >> Real >> A_String_Operator >> Imaginary; Are you compiling and testing these things before asking? Always edit, compile, and test in tiny little cycles, adding one ability at a time. -- Phlip http://industrialxp.org/community/bi...UserInterfaces Jul 22 '05 #21

 P: n/a Hi Phlip, Is it possible to use any symbol I want to define an operator, e.g.: Complex & Complex::operator $( Complex const & z ) Complex C = 5$ 1; Sorry about the bad syntax in my last post, I meant: float Real; String A_String_Operator; float Imaginary; cout << "Enter z," " ( in the form: Real + Imaginary, " " spaces required ): "; cin >> Real >> A_String_Operator >> Imaginary; I don't have any console applications to test this in, so I didn't bother to compile it, And I never use cout or cin myself. Jul 22 '05 #22

 P: n/a Hi JKop, Here's how I'd explain what a " temporary " is: int & In_A_Stack ( ) { // 1 here is a temporary, because it's in a stack. return 1; } int main ( ) { // This puts 6 in a stack somewhere, // but it will soon be overwritten, // as the stack will soon be popped. In_A_Stack () = 6; } Jul 22 '05 #23

 P: n/a Hi John Harrison, So, Given: int Same_Thing_As_Reference ; int & Reference = Same_Thing_As_Reference ; The = symbol " binds " Same_Thing_As_Reference to Reference. Hence, Whatever happens to Reference also happens to Same_Thing_As_Reference, because they are the same thing. Jul 22 '05 #24

 P: n/a Jeff Relf wrote: Is it possible to use any symbol I want to define an operator, e.g.: Complex & Complex::operator $( Complex const & z ) Complex C = 5$ 1; No. Your friendly neighborhood C++ tutorial might list the ones you can use. They include |=, comma, and [], but not # or $or {}. The above code attempts to create "syntactic sugar". If Complex needs two arguments to construct, then it needs a constructor that takes two arguments. Sorry about the bad syntax in my last post, I meant: float Real; String A_String_Operator; float Imaginary; cout << "Enter z," " ( in the form: Real + Imaginary, " " spaces required ): "; cin >> Real >> A_String_Operator >> Imaginary; I don't have any console applications to test this in, so I didn't bother to compile it, And I never use cout or cin myself. I can't repair car engines, and I don't have a car, but I have a spark plug. What should I set its gap to? Your questions must come from your direct experience attempting to write these programs. Else the group will mire in endless distractions, such as the difference between String and std::string. Regardless of how you collect user input, here's the Miniature Language Pattern for C++: typedef std::map params_t; typedef bool (*case_t)(params_t &); std::map testCommands; bool quotient(params_t & testCase) { double num (strtod(testCase["numerator" ].c_str(), NULL)); double den (strtod(testCase["denominator"].c_str(), NULL)); double quo (strtod(testCase["quotient()" ].c_str(), NULL)); return num / den == quo; } bool sum(params_t & testCase) { double num (strtod(testCase["augend"].c_str(), NULL)); double den (strtod(testCase["addend"].c_str(), NULL)); double quo (strtod(testCase["sum()" ].c_str(), NULL)); return num + den == quo; } bool Product(params_t & testCase) { double num (strtod(testCase["Input1"].c_str(), NULL)); double den (strtod(testCase["Input2"].c_str(), NULL)); double quo (strtod(testCase["Product()" ].c_str(), NULL)); return num * den == quo; } void registerListOfActions() { testCommands["quotient()"] = quotient; testCommands["sum()" ] = sum; testCommands["Product()" ] = Product; } Now when you call this... case_t case_ = testCommands[key]; if (case_) return case_(testCase); ....if key is "Product()" you call the Product() function, and if key is "sum()" you call sum(), etc. The arguments to the function go in as a map of strings in testCase: testCase["Input1"] = 5; testCase["Input2"] = 2; testCase["Product()"] = 10; -- Phlip http://industrialxp.org/community/bi...UserInterfaces Jul 22 '05 #25  P: n/a Hi Phlip, You mentioned, " If Complex needs two arguments to construct, then it needs a constructor that takes two arguments. " So then, No symbol can be used to create a complex number from integers. Hence, One must do something like: Complex( 3, 2 ); You showed: typedef std::map params_t; You lost me at: map < string, string > Oh well, no big deal. Jul 22 '05 #26  P: n/a Jeff Relf wrote: You mentioned, " If Complex needs two arguments to construct, then it needs a constructor that takes two arguments. " Your editor probably supports "reply ticks". They make these replies easier to write and read. So then, No symbol can be used to create a complex number from integers. Hence, One must do something like: Complex( 3, 2 ); No, I said$ could not, and that such a symbol would be syntactic sugar. But if you like to overloading operator!=, that would break much code that uses != with two integer arguments, so overloading an operator would indeed be difficult. You showed: typedef std::map params_t; You lost me at: map < string, string > Read the book /Accelerated C++/. -- Phlip http://industrialxp.org/community/bi...UserInterfaces Jul 22 '05 #27

 P: n/a Jeff Relf wrote: Hi Phlip, You noted, " But if you [ overloaded the ] operator !=, that would break much code that uses != with two integer arguments, so overloading an operator would indeed be difficult. " That must be the understatement of the year. As for my quoting style, That's just the way that I prefer it. I don't like the usual quoting methods. Then prepare to not getting answers. It is you who wants help, not us. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #30