difference in following code

W

waltbrad

For an exercise I had to write a class that would do math operations
on complex numbers. The main point of the exercise was overloading
various operators. One of them was the conjugate operator "~".

I overloaded it thus:

void Complecks::eek:perator~(const Complecks& q)const{

im = - im;
}

I figured the invoking object would have it's "im" member negated,
which seemed to be the purpose. But that didn't work. Fortunately
for me, the author of this book gave the solution to this problem and
his method was:

Complecks Complecks::eek:perator~(const Complecks& q)const{
Complecks t;
t.real = real - q.real;
t.im = im - q.im;
return t;
}

Okay. But the method is invoked with a call like " ~c " where c
is a complex number with a real and imaginary component, no
assignement operator is involved. So, doesn't the latter code just
return back to "c"? Why wouldn't the first code work the same?
 
V

Victor Bazarov

waltbrad said:
For an exercise I had to write a class that would do math operations
on complex numbers. The main point of the exercise was overloading
various operators. One of them was the conjugate operator "~".

I overloaded it thus:

void Complecks::eek:perator~(const Complecks& q)const{

im = - im;

What's 'im'? Is that a member? Of what, 'q' or '*this'? If it's
(supposedly) the member of '*this', then you're trying to change the
'*this' object, right? And you just declared that object 'const' by
putting 'const' after the function declaration (before the curly
brace). So, even if the syntax were accepted (I don't think it
should be, since ~ is an unary operator, so it shouldn't have any
arguments), the compilation shouldn't let you change a const object.
}

I figured the invoking object would have it's "im" member negated,
which seemed to be the purpose. But that didn't work. Fortunately
for me, the author of this book

*What* book? I am asking so that we'd recommend people against it
since it doesn't seem to have correct C++ examples.
gave the solution to this problem and
his method was:

Complecks Complecks::eek:perator~(const Complecks& q)const{
Complecks t;
t.real = real - q.real;
t.im = im - q.im;
return t;
}

Okay.

OKAY? Are you saying it will compile? How is 'Complecks' defined?
But the method is invoked with a call like " ~c " where c
is a complex number with a real and imaginary component, no
assignement operator is involved. So, doesn't the latter code just
return back to "c"?
No.

Why wouldn't the first code work the same?

It's up to you of course, but the operator~ (just like the operator!
or the operator-) is NOT supposed to change the object for which it
is called. It is supposed to return a new object:

Complecks Complecks::eek:perator~() const {
return Complecks(real, -im); // there is a c-tor for that I hope
}

or

Complecks operator~(Complecks const& q) {
return Complecks(q.real(), -q.imaginary());
}

(supposing that you have defined 'Complecks' with needed constructor
and accessors).

V
 
B

BobR

Victor Bazarov said:
What's 'im'? Is that a member? Of what, 'q' or '*this'? If it's
(supposedly) the member of '*this', then you're trying to change the
'*this' object, right? And you just declared that object 'const' by
putting 'const' after the function declaration (before the curly
brace). So, even if the syntax were accepted
** (I don't think it
should be, since ~ is an unary operator, so it shouldn't have any
arguments) ** ....

It should have one argument.

"TiCpp" v1 says:

" The bitwise not (~, also called the ones complement operator) is a unary
operator - it only takes ** one argument ** (all other bitwise operators are
binary operators). Bitwise not produces the opposite of the input bit - a
one if the input bit is zero, a zero if the input bit is one.
"
I think you meant that if a 'this' pointer is passed in, the '&q' arg makes
it two?
[ so make it 'static' member. <G> ]
 
V

Victor Bazarov

BobR said:
It should have one argument.

A non-static member shouldn't have any _additional_ arguments. Some
(many) newbies do not realise that there is an implicit argument for
any non-static member function, so my note was for those.
"TiCpp" v1 says:

" The bitwise not (~, also called the ones complement operator) is a
unary operator - it only takes ** one argument ** (all other bitwise
operators are binary operators). Bitwise not produces the opposite of
the input bit - a one if the input bit is zero, a zero if the input
bit is one. "
I think you meant that if a 'this' pointer is passed in, the '&q' arg
makes it two?
[ so make it 'static' member. <G> ]

I think there may be a problem with that. Any overloaded operators
(except 'new', 'new[]', 'delete', and 'delete[]') should be either
non-static members or non-members.

V
 
W

waltbrad

What's 'im'? Is that a member? Of what, 'q' or '*this'? If it's
(supposedly) the member of '*this', then you're trying to change the
'*this' object, right? And you just declared that object 'const' by
putting 'const' after the function declaration (before the curly
brace). So, even if the syntax were accepted (I don't think it
should be, since ~ is an unary operator, so it shouldn't have any
arguments), the compilation shouldn't let you change a const object.

Hello. Sorry about the delayed response. I did follow up a yesterday
but for some reason my post never showed up.

Yes, 'im' is a member. Well, you have pretty much clarified things a
bit for me. Yes, I did think I was dealing with a 'this' pointer. And,
apparently there is one. But, I completely ignored that this was
const function.

*What* book? I am asking so that we'd recommend people against it
since it doesn't seem to have correct C++ examples.

Stephen Prata's "C++ Primer Plus". It actually is not the book's
fault. The blame resides with my difficulty in grasping the material. C
++ is a very complicated language. I was trying to learn through
reading Deitel & Deitel's 4th edition, but six weeks and 600 pages
into that book I had to set it down. Then I turned to Prata and he is
at least giving me some handle on the language. But it still takes a
lot of work, a lot of time and a lot of practice. I also have tic++
on my harddrive and I will be reading that down the road. But over
half way through Prata. But, if you have a recommendation I'm open to
suggestions. "Accelerated C++" left me in the dust, though.

OKAY? Are you saying it will compile? How is 'Complecks' defined?
Yes, this code compiles and runs fine. Why not? It does create a new
object. Unless you mean that the expressions imply that there is
indeed a "this" pointer. I guess there does have to be a "this"
pointer.

================
class Complecks{
private:
double real;
double im;

public:
Complecks();
Complecks(double p, double q);
Complecks operator+(const Complecks& q)const;
Complecks operator-(const Complecks& q)const;
Complecks operator*(const Complecks& q)const;
Complecks operator~();
friend Complecks operator*(double x, const Complecks& q);
friend std::eek:stream& operator<<(std::eek:stream& os, const Complecks&
q);
friend std::istream& operator>>(std::istream& is, Complecks& q);
};
===========================
and then...

===========
//one of two constructors:

Complecks::Complecks(double p, double q){
real = p;
im = q;
}

//and the final way I implemented the "~" operator:

Complecks Complecks::eek:perator~(){
Complecks obj;
obj.real = real;
obj.im = -im;
return obj;
}
================

I don't know if this is all you want to see or not. But apparently
there is a "this" operator.
Right. Here I was wrong. Although the example program didn't use "~c"
with an assignment operator, it could have done that. Instead the "~c"
was used in an ostream, and it returned the value to the ostream.
But, I guess the only reason the overloaded operator wouldn't return a
value with the first code was that it was declared void and constant.

It's up to you of course, but the operator~ (just like the operator!
or the operator-) is NOT supposed to change the object for which it
is called. It is supposed to return a new object:

Complecks Complecks::eek:perator~() const {
return Complecks(real, -im); // there is a c-tor for that I hope
}

Yes, your code would also work.
or

Complecks operator~(Complecks const& q) {
return Complecks(q.real(), -q.imaginary());
}

(supposing that you have defined 'Complecks' with needed constructor
and accessors).
This wouldn't work with the code I have, but yes, I can see how that
would work with the right setup.

Thanks for your input, I think this has cleared up some of my
understanding. But, do you agree that the overloaded ~ operator
function does have a "this" pointer?
 
V

Victor Bazarov

^^^^^^^^^^^^^^^^^^
You seem to have completely ignored my comment about the argument here.
No matter.
Hello. Sorry about the delayed response. I did follow up a yesterday
but for some reason my post never showed up.

Yes, 'im' is a member. Well, you have pretty much clarified things a
bit for me. Yes, I did think I was dealing with a 'this' pointer. And,
apparently there is one. But, I completely ignored that this was
const function.



Stephen Prata's "C++ Primer Plus". It actually is not the book's
fault. The blame resides with my difficulty in grasping the material.
C ++ is a very complicated language. I was trying to learn through
reading Deitel & Deitel's 4th edition, but six weeks and 600 pages
into that book I had to set it down. Then I turned to Prata and he is
at least giving me some handle on the language. But it still takes a
lot of work, a lot of time and a lot of practice. I also have tic++
on my harddrive and I will be reading that down the road. But over
half way through Prata. But, if you have a recommendation I'm open to
suggestions. "Accelerated C++" left me in the dust, though.


Yes, this code compiles and runs fine. Why not?

<shrug> The code you posted earlier and the one you posted later
are _different_. Do you really want to know why the code you posted
originally shouldn't compile? Well, for one, operator ~ is unary,
if it's defined as a member, like you showed originally, it should
NOT have any explicit arguments (like in the code you posted later).
And I already told you that...
It does create a new
object. Unless you mean that the expressions imply that there is
indeed a "this" pointer. I guess there does have to be a "this"
pointer.

================
class Complecks{
private:
double real;
double im;

public:
Complecks();
Complecks(double p, double q);
Complecks operator+(const Complecks& q)const;
Complecks operator-(const Complecks& q)const;
Complecks operator*(const Complecks& q)const;
Complecks operator~();
^^^
Can you see that there is no argument here? Now look at your
original post, please.
friend Complecks operator*(double x, const Complecks& q);
friend std::eek:stream& operator<<(std::eek:stream& os, const Complecks&
q);
friend std::istream& operator>>(std::istream& is, Complecks& q);
};
===========================
and then...

===========
//one of two constructors:

Complecks::Complecks(double p, double q){
real = p;
im = q;
}

//and the final way I implemented the "~" operator:

Complecks Complecks::eek:perator~(){
^^^^^^^^^
And no argument here either?
Complecks obj;
obj.real = real;
obj.im = -im;
return obj;
}
================

I don't know if this is all you want to see or not.

I want _you_ to see it.
But apparently
there is a "this" operator.

[..], do you agree that the overloaded ~ operator
function does have a "this" pointer?

Since the operator is defines as a non-static member function,
there can be no doubt about it.

V
 
W

waltbrad

You seem to have completely ignored my comment about the argument here.
No matter.
And no argument here either?
Complecks obj;
obj.real = real;
obj.im = -im;
return obj;
}
================
I don't know if this is all you want to see or not.

I want _you_ to see it.
But apparently
there is a "this" operator.
[..], do you agree that the overloaded ~ operator
function does have a "this" pointer?

Since the operator is defines as a non-static member function,
there can be no doubt about it.

Hmmmm... Sorry, Victor. I guess I have a little too much code laying
around. I'll have to look at this again a little bit later. Thanks.
 
B

BobR

Victor Bazarov wrote in message...
BobR said:
[ so make it 'static' member. <G> ]

I think there may be a problem with that. Any overloaded operators
(except 'new', 'new[]', 'delete', and 'delete[]') should be either
non-static members or non-members.

Yeah, Mr. Eckel demonstrates the overloads using 'friend', but lately, that
style seems to be getting the dumpster. [1]

You did notice the grin (<G>) in there, didn't you? ;-}

[1] reference: TiCpp v1

file://: C12:OverloadingUnaryOperators.cpp
// Non-member functions:
class Integer {
long i;
Integer* This() { return this; }
public:
Integer(long ll = 0) : i(ll) {}
// No side effects takes const& argument:
friend const Integer& operator+(const Integer& a);
friend const Integer operator-(const Integer& a);
friend const Integer operator~(const Integer& a);
// snip rest
};

// snip rest
const Integer operator~(const Integer& a) {
cout << "~Integer\n";
return Integer(~a.i);
}
// snip rest
 
W

waltbrad

Yes, I definitely botched that up. That was not the author's solution
that I printed in the first post. That was my misreading of his
solution. I guess I was relying too much on a rote of understanding of
how to overload these operators. It worked for the binary operators,
but the holes in my understanding really showed through with the
unary.

So, if you'll bear with me here I just want to recap my "current"
understanding and see if you'll verify that I have this right.

Given that A, B and C are fellow class objects the statement:

C = A + B;

could be written as the following function call, (given that the
operator was overloaded correctly):

C = A.operator+(B);

But with a unary operator, the statement:

~c

would have a function call like:

c.operator~();

So, c is the invoking object and the "this" operator contains the
address of c.

Further, the function definition for the overloaded unary operator:

* creates a new object that it returns; so the return type could not
be "void".

* the purpose of any of the overloaded operators is to return a new
object; so the function does NOT alter the invoking object.

* the overloaded unary operator will only have ONE argument if it is
declared as a friend funtion. But as a member function it has no
argument.

Sorry for being such a pain. I do believe I carry a greater
understanding of these operators in general now though.

Thanks again.
 
V

Victor Bazarov

waltbrad said:
Yes, I definitely botched that up. That was not the author's solution
that I printed in the first post. That was my misreading of his
solution. I guess I was relying too much on a rote of understanding of
how to overload these operators. It worked for the binary operators,
but the holes in my understanding really showed through with the
unary.

So, if you'll bear with me here I just want to recap my "current"
understanding and see if you'll verify that I have this right.

Given that A, B and C are fellow class objects the statement:

C = A + B;

could be written as the following function call, (given that the
operator was overloaded correctly):

C = A.operator+(B);

That presumes the operator was overloaded as a member. It does not
have to have been. It could be overloaded as a non-member, then the
actual call is

C = operator+(A, B);
But with a unary operator, the statement:

~c

would have a function call like:

c.operator~();

Again, that's if it's a member.
So, c is the invoking object and the "this" operator contains the
address of c.
Right.

Further, the function definition for the overloaded unary operator:

* creates a new object that it returns; so the return type could not
be "void".

It's up to the designer. If the return value is supposed to designate
the result, it should return it.
* the purpose of any of the overloaded operators is to return a new
object; so the function does NOT alter the invoking object.

That's not necessarily true. Pre-increment operator, for example,
does change the value of the object for which it's invoked.
* the overloaded unary operator will only have ONE argument if it is
declared as a friend funtion. But as a member function it has no
argument.

...has no *explicit* argument.
Sorry for being such a pain. I do believe I carry a greater
understanding of these operators in general now though.

Good. Glad to be of help.

V
 

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

Forum statistics

Threads
474,292
Messages
2,571,494
Members
48,180
Latest member
DelmarCarv

Latest Threads

Top