Members or not

M

Marcin Kalicinski

Hi all,

What is the best practice with redefining operators for a class:

namespace Math
{

class Matrix
{
// ...
bool operator ==(const Matrix &) const; // (1)
}

bool operator ==(const Matrix &, const Matrix &); // (2)
}

Should (1) or (2) be preferred? All data members of Matrix are public, so
there's no problem of access.

In my program I have more "concrete" mathematical classes like Matrix, and I
want to define operators like ==, +, - etc. consistently for all of them.
Which way should I do it best?

Marcin
 
J

John Harrison

Marcin Kalicinski said:
Hi all,

What is the best practice with redefining operators for a class:

namespace Math
{

class Matrix
{
// ...
bool operator ==(const Matrix &) const; // (1)
}

bool operator ==(const Matrix &, const Matrix &); // (2)
}

Should (1) or (2) be preferred? All data members of Matrix are public, so
there's no problem of access.

For an equality operator 2 should be prefered.

Here's why, this compiles

struct X
{
X(int);
};

extern bool operator==(const X&, const X&); // version 2

int main()
{
X x;
if (1 == x)
;
if (x == 1)
;
}

but this doesn't

struct X
{
X(int);
bool operator==(const X&) const; // version 1
};


int main()
{
X x;
if (1 == x) // error here
;
if (x == 1)
;
}

By using a member function instead of a free function you impose different
rules on the conversions that can happen for the first and second
parameters. C++ will not construct a teemporary X from an int in the case
commented 'error here' but will do for every other case. Obviously this
assymetry is a bad idea for something like equality.
In my program I have more "concrete" mathematical classes like Matrix, and I
want to define operators like ==, +, - etc. consistently for all of them.
Which way should I do it best?

Usually only assignment operators, =, +=, *= etc are defined as members.

john
 
R

Ron Samuel Klatchko

Marcin Kalicinski said:
Hi all,

What is the best practice with redefining operators for a class:

namespace Math
{

class Matrix
{
// ...
bool operator ==(const Matrix &) const; // (1)
}

bool operator ==(const Matrix &, const Matrix &); // (2)
}

Should (1) or (2) be preferred? All data members of Matrix are public, so
there's no problem of access.

One limitation of #2 is that the lhs must be a matrix. If you had a
constructor that took a SomeOtherMatrix class and you had the following
code.

Matrix m;
SomeOtherMatrix sm;

if (m == sm) // (a)
if (sm == m) // (b)

Both (a) and (b) will work with (2) but only (a) will work with (1).

That said, using public data members isn't very good style. You can either
make the operator== a friend or you can just use the operator== as a
forwarding function:

class Matrix
{
...
bool equal(const Matrix &other) const;
...
};

inline bool operator==(const Matrix &m1, const Matrix &m2)
{
return m1.eq(m2);
}

samuel
 
I

Ioannis Vranos

Marcin said:
Hi all,

What is the best practice with redefining operators for a class:

namespace Math
{

class Matrix
{
// ...
bool operator ==(const Matrix &) const; // (1)
}

bool operator ==(const Matrix &, const Matrix &); // (2)
}

Should (1) or (2) be preferred? All data members of Matrix are public, so
there's no problem of access.

In my program I have more "concrete" mathematical classes like Matrix, and I
want to define operators like ==, +, - etc. consistently for all of them.
Which way should I do it best?

Marcin



A good approach used by many is two use the two operand definition (your
(2)) for objects of different types, while for objects of the same type
to use the one operand definition inside the class.






Best regards,

Ioannis Vranos
 
M

Marcin Kalicinski

U¿ytkownik "John Harrison said:
For an equality operator 2 should be prefered.

Here's why, this compiles

struct X
{
X(int);
};

extern bool operator==(const X&, const X&); // version 2

int main()
{
X x;
if (1 == x)
;
if (x == 1)
;
}

but this doesn't

struct X
{
X(int);
bool operator==(const X&) const; // version 1
};


int main()
{
X x;
if (1 == x) // error here
;
if (x == 1)
;
}

By using a member function instead of a free function you impose different
rules on the conversions that can happen for the first and second
parameters. C++ will not construct a teemporary X from an int in the case
commented 'error here' but will do for every other case. Obviously this
assymetry is a bad idea for something like equality.
and

Usually only assignment operators, =, +=, *= etc are defined as members.

I know that operator = must be a member, but operators +=, *= etc. do not
have to be. Is there any rationale on making them members anyway?

Marcin
 
J

John Harrison

I know that operator = must be a member, but operators +=, *= etc. do not
have to be. Is there any rationale on making them members anyway?

I can't think of any reason why making operator+= global would not work, but
since operator+= operates on a single object it makes sense to me to have it
as a member function.

john
 
I

Ioannis Vranos

John said:
I can't think of any reason why making operator+= global would not work, but
since operator+= operates on a single object it makes sense to me to have it
as a member function.

john


As I have told in another message, a good approach is to use the two
operand definition for objects of different types, while for objects of
the same type to use the one operand definition inside the class.


For example if we have our type Something to interact with some other
type, we will use the two operand operator definition.

If we want to define operators for objects of the same type we will use
the one operand definitions.

So if we want our class to interact with some other type with +=, we
will use the two operand definition (outside of the class), while for an
operator+= for interaction between objects of our class, we will use the
one operand definition (inside our class).


A more specific example is if we want to define an operator<< among
ostream (cout) and our class Sometype, we will provide a two operand
definition. The same applies for operator>> between istream (cin) and
our type, we will define a two operand definition outside our class.


This also helps maintainability and extensibility.






Regards,

Ioannis Vranos
 

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
474,171
Messages
2,570,935
Members
47,472
Latest member
KarissaBor

Latest Threads

Top