From: Keith Thompson on
Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
> Thanks for all the replies on this. I spent part of the day playing
> around with this, and was able to define constructors, member
> functions, etc for a test "struct" following the examples given for a
> class construction. I was also able to define some overloaded
> operators as well, and it all seems to be working as expected. So I
> think I'm learning.
>
> I do have one other question though. My test structure looks like this:
>
>
> ****************************************
> struct Point
> {
> double x;
> double y;
>
> Point(double u=0, double v=0); //...Constructor
> Point operator*(const double & b) const; //...Allows multiplying
> a point by scalar.

Usenet software typically wraps long lines. If you can keep your code
down to about 72 columns, you can avoid the problems this causes.

Why do you declare the parameters as "const double & b" rather than
just "double b"?

>
> };

Just as a matter of style, I'd declare this with the "class" keyword
rather than the "struct" keyword, with an explicit "public:" after the
opening brace. The way you did it is perfectly legal.

> // Member functions
>
> Point::Point(double u, double v) //...Constructor
> {
> x=u;
> y=v;
> }

This could be done more cleanly with an initializer list:

Point::Point(double u=0, double v=0) : x(u), y(v) {}

And you might consider using a consistent naming convention for
constructor parameters that correspond to members. I've seen trailing
underscores used for this:

Point::Point(double x_=0, double y_=0) : x(x_), y(y_) {}

> Point Point::operator*(const double & b) const
> {
> return Point(x*b,y*b);
> }
>
> *****************************************
>
> The overloaded operator works fine if the scalar comes after the point
> variable, but not if it comes before.
>
> ie.
> Point p1(1,2); //...Define point p1
> Point p2 = p1*5; //...This works
> Point p3 = 5*pi //...This doesn't! Generates an error
>
> Is there anyway to define an overloaded * so 5*p1 works also? It's
> not a big deal, if not, but it would be convenient not to have to
> think about the order when it comes time to actually use this in my
> code.

Sure, you can declare an overloaded operator* that takes a double
and a Point. It just can't be a member of the class or struct.
It will take two explicitly declared parameters (no "this").

--
Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
From: Pat on
Keith Thompson wrote:
> Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
>> Thanks for all the replies on this. I spent part of the day playing
>> around with this, and was able to define constructors, member
>> functions, etc for a test "struct" following the examples given for a
>> class construction. I was also able to define some overloaded
>> operators as well, and it all seems to be working as expected. So I
>> think I'm learning.
>>
>> I do have one other question though. My test structure looks like this:
>>
>>
>> ****************************************
>> struct Point
>> {
>> double x;
>> double y;
>>
>> Point(double u=0, double v=0); //...Constructor
>> Point operator*(const double & b) const; //...Allows multiplying
>> a point by scalar.
>
> Usenet software typically wraps long lines. If you can keep your code
> down to about 72 columns, you can avoid the problems this causes.

ok.

>
> Why do you declare the parameters as "const double & b" rather than
> just "double b"?
>

It's my understanding that it's more efficient (ie faster and more
memory efficient) to pass an argument by reference than by value. Since
a reference allows the actual variable (not a copy) to be used, the
"const" is added to prevented it from being altered accidentally.


>> };
>
> Just as a matter of style, I'd declare this with the "class" keyword
> rather than the "struct" keyword, with an explicit "public:" after the
> opening brace. The way you did it is perfectly legal.
>
I started off using a struct mainly because that's what I knew (as a
newbie to C++). But now that I've become familiar with classes and how
they work, I probably just change it to a class, as you suggested, and
do it the "right" way! ;^). There doesn't appear to be any advantage to
keeping it as a struct.



>> // Member functions
>>
>> Point::Point(double u, double v) //...Constructor
>> {
>> x=u;
>> y=v;
>> }
>
> This could be done more cleanly with an initializer list:
>
> Point::Point(double u=0, double v=0) : x(u), y(v) {}

Thanks for the suggestion. I've never used an initializer list but will
look into it. So if I do this, then I assume I can remove the
initialization in the constructor prototype. Is that right?

>
> And you might consider using a consistent naming convention for
> constructor parameters that correspond to members. I've seen trailing
> underscores used for this:
>
> Point::Point(double x_=0, double y_=0) : x(x_), y(y_) {}
>
Thanks for the suggest. Looks like a good approach.


>> Point Point::operator*(const double & b) const
>> {
>> return Point(x*b,y*b);
>> }
>>
>> *****************************************
>>
>> The overloaded operator works fine if the scalar comes after the point
>> variable, but not if it comes before.
>>
>> ie.
>> Point p1(1,2); //...Define point p1
>> Point p2 = p1*5; //...This works
>> Point p3 = 5*pi //...This doesn't! Generates an error
>>
>> Is there anyway to define an overloaded * so 5*p1 works also? It's
>> not a big deal, if not, but it would be convenient not to have to
>> think about the order when it comes time to actually use this in my
>> code.
>
> Sure, you can declare an overloaded operator* that takes a double
> and a Point. It just can't be a member of the class or struct.
> It will take two explicitly declared parameters (no "this").
>

Thanks. Today I reviewed the use of "friend functions" and it appears
these are just for this situation. The reference I was reading (C++
Primer Plus) actually had an example like this (multiplying an object by
a constant) so I know how to do this now.

Thanks again for suggestions. They were helpful. -Pat



From: Keith Thompson on
Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
> Keith Thompson wrote:
>> Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
[...]
>>> Point operator*(const double & b) const; //...Allows multiplying
>>> a point by scalar.
[...]
>> Why do you declare the parameters as "const double & b" rather than
>> just "double b"?
>
> It's my understanding that it's more efficient (ie faster and more
> memory efficient) to pass an argument by reference than by value.
> Since a reference allows the actual variable (not a copy) to be used,
> the "const" is added to prevented it from being altered accidentally.

That's true for large objects, but not for small ones.

Passing by reference is (probably) implemented by passing the
address of the argument. It also means that each type you refer to
the parameter, the generated code has to fetch or store the value
indirectly. For a large class or struct parameter, it's worthwhile.
For an int, it's probably cheaper to pass the value directly.
For a double, it could go either way.

[...]

>> Sure, you can declare an overloaded operator* that takes a double
>> and a Point. It just can't be a member of the class or struct.
>> It will take two explicitly declared parameters (no "this").
>
> Thanks. Today I reviewed the use of "friend functions" and it appears
> these are just for this situation. The reference I was reading (C++
> Primer Plus) actually had an example like this (multiplying an object
> by a constant) so I know how to do this now.

Note that in this case the overload operator* doesn't need to be a
"friend"; it can work with just information that's publicly available.

--
Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
From: Keith Thompson on
Keith Thompson <kst-u(a)mib.org> writes:
[...]
> Passing by reference is (probably) implemented by passing the
> address of the argument. It also means that each type you refer to

Typo: each *time* you refer to the parameter.

> the parameter, the generated code has to fetch or store the value
> indirectly. For a large class or struct parameter, it's worthwhile.
> For an int, it's probably cheaper to pass the value directly.
> For a double, it could go either way.
[...]

--
Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
From: Pat on
Keith Thompson wrote:
> Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
>> Keith Thompson wrote:
>>> Pat <pkelecy@_REMOVETHIS_gmail.com> writes:
> [...]
>>>> Point operator*(const double & b) const; //...Allows multiplying
>>>> a point by scalar.
> [...]
>>> Why do you declare the parameters as "const double & b" rather than
>>> just "double b"?
>> It's my understanding that it's more efficient (ie faster and more
>> memory efficient) to pass an argument by reference than by value.
>> Since a reference allows the actual variable (not a copy) to be used,
>> the "const" is added to prevented it from being altered accidentally.
>
> That's true for large objects, but not for small ones.
>
> Passing by reference is (probably) implemented by passing the
> address of the argument. It also means that each type you refer to
> the parameter, the generated code has to fetch or store the value
> indirectly. For a large class or struct parameter, it's worthwhile.
> For an int, it's probably cheaper to pass the value directly.
> For a double, it could go either way.

Ok. Makes sense.


>
> [...]
>
>>> Sure, you can declare an overloaded operator* that takes a double
>>> and a Point. It just can't be a member of the class or struct.
>>> It will take two explicitly declared parameters (no "this").
>> Thanks. Today I reviewed the use of "friend functions" and it appears
>> these are just for this situation. The reference I was reading (C++
>> Primer Plus) actually had an example like this (multiplying an object
>> by a constant) so I know how to do this now.
>
> Note that in this case the overload operator* doesn't need to be a
> "friend"; it can work with just information that's publicly available.

Wow. I think I'm finally seeing the light. I just tested this and
you're right. I can define these overaloaded operators just like
"ordinary" functions, passing my Point structures (or any other type) as
arguments. No need for all the formalism of a class. I think I've now
come full circle, as this is the solution I was originally asking for.
I'm surprised the three or so C++ books I've been referring to didn't
mention this when introducing operator overloading, instead of making it
seem like it was a class-only feature. At least I know how classes work
now.

Thanks for pointing the way! I appreciate it. :^) -Pat