Question about overloaded operators and constructors

I

iluvatar

Hi all.

I have written a 3d-vector class (for 3-dimensional space) and I have
overloaded the arihtmetic operators like +, +=, * and so on. Also, the
constructor works with doubles and has default arguments.

In my class, the operator = works for another vector (just copying the
elements), and for a double: in this cases each element of the vector
will be equal to the double. Example:

Vector3D v1;
Vector3D v2 = v1; // v2.x = v1.x, v2.y = v1.y, v2.z = v1.z

double num = 3.0;
Vector3D v2 = num; // v2.x = 3.0, v2.y = 3.0, v2.z = 3.0

Also, I have overloaded the operator *: in the case of tho vector,
like v1*v2, this is just the dot product. But when I writte
v2 = v1*num ; // it means: v2.x = (v1.x)*num, v2.y = (v1.y)*num, v2.z
= (v1.z)*num

My question is: When I have expressions like
v3 = v1*num*num2;

How can I know that I get what I want, i.e., the number num*num2
multiplying the vector v1 and then asigned to v3, and not, for
example, a temporal vector constructed with num, then a dot product
with v1, then multiplication with num2 and at last a new construction
of a vector to assign to v3?

There is some precedence in the constructor and the overloaded
operators?

Thanks in advance.
 
V

Victor Bazarov

iluvatar said:
I have written a 3d-vector class (for 3-dimensional space) and I have
overloaded the arihtmetic operators like +, +=, * and so on. Also, the
constructor works with doubles and has default arguments.

In my class, the operator = works for another vector (just copying the
elements), and for a double: in this cases each element of the vector
will be equal to the double. Example:

Vector3D v1;
Vector3D v2 = v1; // v2.x = v1.x, v2.y = v1.y, v2.z = v1.z

double num = 3.0;
Vector3D v2 = num; // v2.x = 3.0, v2.y = 3.0, v2.z = 3.0

Also, I have overloaded the operator *: in the case of tho vector,
like v1*v2, this is just the dot product. But when I writte
v2 = v1*num ; // it means: v2.x = (v1.x)*num, v2.y = (v1.y)*num, v2.z
= (v1.z)*num

My question is: When I have expressions like
v3 = v1*num*num2;

How can I know that I get what I want, i.e., the number num*num2
multiplying the vector v1 and then asigned to v3, and not, for
example, a temporal vector constructed with num, then a dot product
with v1, then multiplication with num2 and at last a new construction
of a vector to assign to v3?

There is some precedence in the constructor and the overloaded
operators?

Yes, there is always precedence. In the case you asked about you
get

( v3 = ( ( v1 * num ) * num2) )

That's how it's parsed and there can be no other way. It's dictated
by the language grammar. Now, every subexpression can be interpreted
differently (and that's what you seem to be concerned with).

Well, in order to invoke the operator * for two vectors when you
write 'v1 * num', the compiler has to convert 'num' to a vector first,
and to invoke the operator * for a vector and a number, there is no
conversion needed. The operation selected is the one with the fewer
conversions, in this case the multiplication with a scalar.

All those rules are actually written in the Standard (and probably
explained in some good books). I use the Standard. Those who use
books will hopefully chime in and recommend them.

V
 
S

Sylvester Hesp

iluvatar said:
Hi all.

I have written a 3d-vector class (for 3-dimensional space) and I have
overloaded the arihtmetic operators like +, +=, * and so on. Also, the
constructor works with doubles and has default arguments.

In my class, the operator = works for another vector (just copying the
elements), and for a double: in this cases each element of the vector
will be equal to the double. Example:

Vector3D v1;
Vector3D v2 = v1; // v2.x = v1.x, v2.y = v1.y, v2.z = v1.z

double num = 3.0;
Vector3D v2 = num; // v2.x = 3.0, v2.y = 3.0, v2.z = 3.0

Also, I have overloaded the operator *: in the case of tho vector,
like v1*v2, this is just the dot product. But when I writte
v2 = v1*num ; // it means: v2.x = (v1.x)*num, v2.y = (v1.y)*num, v2.z
= (v1.z)*num

My question is: When I have expressions like
v3 = v1*num*num2;

How can I know that I get what I want, i.e., the number num*num2
multiplying the vector v1 and then asigned to v3, and not, for
example, a temporal vector constructed with num, then a dot product
with v1, then multiplication with num2 and at last a new construction
of a vector to assign to v3?

There is some precedence in the constructor and the overloaded
operators?

Thanks in advance.

If you have a Vector that takes a scalar (float or double or something
similar) as argument to construct a vector with all components set to that
value, like you explained, make that constructor explicit. That way, a
Vector can never be automatically constructed out of a single scalar - you
always have to write Vector(num) instead of just num where a Vector is
expected. Of course, this disables the use of

Vector v = 3.0;

Instead, you'd have to write:

Vector v(3.0);
-or-
Vector v = Vector(3.0);

But aside from that, if you have this class:

class Vector
{
Vector(double scalar = 0.0);
float operator *(const Vector & other); // dot product
Vector operator *(double scalar); // vector multiplication
};

And this expression:

Vector v1, v2;
v1 = v2 * 3.0 * 4.0;

You can assure that the vector multiplication takes precedence over the dot
product according to the overloading rules (Vector::eek:perator*(const Vector&)
needs a conversion while Vector::eek:perator*(double) does not)

- Sylvester
 
S

Sylvester Hesp

Sylvester Hesp said:
If you have a Vector that takes a scalar (float or double or something
similar) as argument to construct a vector with all components set to that
value, like you explained, make that constructor explicit. That way, a
Vector can never be automatically constructed out of a single scalar - you
always have to write Vector(num) instead of just num where a Vector is
expected. Of course, this disables the use of

Vector v = 3.0;

Instead, you'd have to write:

Vector v(3.0);
-or-
Vector v = Vector(3.0);

But aside from that, if you have this class:

class Vector
{
Vector(double scalar = 0.0);
float operator *(const Vector & other); // dot product
Vector operator *(double scalar); // vector multiplication
};

And this expression:

Vector v1, v2;
v1 = v2 * 3.0 * 4.0;

You can assure that the vector multiplication takes precedence over the
dot product according to the overloading rules (Vector::eek:perator*(const
Vector&) needs a conversion while Vector::eek:perator*(double) does not)

- Sylvester

As to what is better from a design-perspective, I think it's better to make
the constructor explicit like I explained. Because scalars aren't vectors,
therefore you shouldn't be able to use a scalar in a place where a vector is
expected, unless you want to explicitely create a vector using that scalar

- Sylvester
 

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
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top