Topic: Assignment operator overloading.
Author: willer@sq.com (Steve Willer)
Date: 1996/12/06 Raw View
stephen.clamage@Eng (Steve Clamage) wrote:
>1. If you don't define an assignment operator, the compiler defines one
>for you. Depending on what declarations appeared in different
>translation units, you could accidently get different semantics for
>assignment in the same program without any warnings. Example:
Of course, this kind of confusion led me to decide long ago to avoid
writing copy operators if at all possible (and it has been possible in
every class I've written so far). With the usage of ref_ptrs
(reference-counting) and copy_ptrs (like auto_ptr except with deep-copy
semantics), I haven't had to deal with this confusion (or destructors,
most of the time).
>2. Simple mistakes that ought to cause compile-time errors could get
>turned into valid code by unexpectedly creating temp objects and
>assigning to them. For example, suppose we have
> T t;
> U u;
> t = u;
>and there is no operator=(T&, U&) but there is a conversion of T to int
>and there is an operator=(int&, U&). You could then wind up creating
>a temporary int, assigning u to it, and discarding the temp, leaving t
>unchanged, and get no complaints from the compiler.
Wouldn't the temporary be const, though?
One of the compilers I use (Borland C++ 5.0) gives a "Temporary used to
initialize <reference>" warning, which *always* points to code errors
like the one you describe. g++ warns about initializing a non-const
reference with a const object.
----
Steve Willer, SoftQuad International, Toronto ON
Work: willer@sq.com Personal: willer@interlog.com CIS: 70400,3667
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: gusty@mail.clark.net (Harlan Messinger)
Date: 1996/12/06 Raw View
cbreece@telogy.com wrote:
>After looking through a draft of the ANSI spec, and not finding an
>adequate explanation for having single variable only assignment operator
>overloading, I thought this news group might be a good place to ask the
>following.
>
This is true for overloading any of the operators: you can change the
semantics (meaning) of an operator, but you can't change its syntax
(grammar). This allows compilers to analyze the syntax of code without
relying on how the programmer has redefined the meaning of the code.
For example,
y = x*&/z
is syntactically incorrect if x, y and z are integers. But if you
write the same expression with x, y and z being objects of some other
type you've define, the overloading rule enables the compiler not to
have to look to see whether you've redefined *, &, or / for that other
type before analyzing the syntax. The alternative would be for
compilers to have to analyze the semantics of your code before being
able to analyze the syntax properly--which would be painful, because a
compiler can efficiently analyze the semantics after it's determined
that the syntax is correct.
Operator = in its normal usage only has one argument on its right hand
side, so you can only overload it with one argument. Similarly, you
can't have an operator / member function with no arguments. You also
can't change the order of evaluation of a sequence of identical
operators: a + b + c is always evaluated as (a + b) + c, and you can't
overload operator + to cause the addition to be evalulated from right
to left.
As far as operator = is concerned, whenever I would LIKE to set the
value of an object based on more than one value, (which usually
corresponds to a situation where there is a constructor that takes the
same set of arguments), I just define an assign() member function.
myclass& myclass::assign(int i, const char *s)
{ ... }
Or (if this isn't a problem in terms of superfluous object
constructions and time-criticality), if you have such a
multi-argument constructor for which you want a parallel assignment
function, and you have a copy assignment operator (or the default one
works correctly for your class), then just write your assignments as
myclass& myclass::operator =(const myclass& someObj) { ... }
// ...
myclass myobj(1, "what's up?");
// Later...
myobj = myclass(3, "hello there");
// Later
myobj = myclass(5, "go home!");
----------
Cruella De Vil / Cruella De Vil / If she don't sell merchandise / No one else will.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: cbreece@telogy.com
Date: 1996/12/04 Raw View
After looking through a draft of the ANSI spec, and not finding an
adequate explanation for having single variable only assignment operator
overloading, I thought this news group might be a good place to ask the
following.
What is wrong with the following, or why is it considered a ``bad
thing''. This seems to be more consistent with the rest of the operator
rules.
class A {
public:
void operator=(int &value, A &instance) {
value = instance.data;
}
operator=(char* &ptr, A &instance) {
ptr = instance.dataPtr;
}
private:
int data;
char *dataPtr;
}
Thanks for the help.
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: stephen.clamage@Eng (Steve Clamage)
Date: 1996/12/04 Raw View
In article 0412960654310001@platinum.telogy.com, cbreece@telogy.com writes:
>After looking through a draft of the ANSI spec, and not finding an
>adequate explanation for having single variable only assignment operator
>overloading, I thought this news group might be a good place to ask the
>following.
>
>What is wrong with the following, or why is it considered a ``bad
>thing''. This seems to be more consistent with the rest of the operator
>rules.
>
>class A {
>public:
> void operator=(int &value, A &instance) {
> value = instance.data;
> }
>
> operator=(char* &ptr, A &instance) {
> ptr = instance.dataPtr;
> }
>
>private:
> int data;
> char *dataPtr;
>}
>
I don't see how you would use the member functions you are defining.
A general member function has an implied "this" parameter, and is
called, for example, like this:
x.fn(args)
An operator member function can also be called with operator syntax,
in which case the left-hand parameter becomes "this". An operator member
function thus has one more parameter than is explicitly declared. Your
examples of a hypothetical operator= would have three parameters. Since
the operator notation for assignment doesn't support three parameters,
I don't see how to call those functions except by writing something like
a1.operator=(k, a2)
In that case, you would be better off using a named function instead of
an operator function, since you could give it a name that described what
was going on. (I can think of several different things a 3-parameter
assignment might do, but I wouldn't know which of them you had in mind.)
You could make your functions static (assuming that were legal) and get
back to the 2-parameter version, but you still couldn't use ordinary
operator notation. You would have to write
A::operator=(k, a1) // k is an int, a1 is an A
because there isn't any way to associate a member function, static or not,
with an expresion like
k = a1 // k is an int, a1 is an A
Once again, this doesn't seem superior to using a named function,
static or non-member.
The solution for most operators is to make them non-member functions,
such as
A operator+(const int&, const A&) { ... }
which then allows you to write
k + a1
The assignment operator is required to be a member function, prohibiting
you from writing one which doesn't take a class object on the left.
There are two main reasons for requiring assignment to be a member:
1. If you don't define an assignment operator, the compiler defines one
for you. Depending on what declarations appeared in different
translation units, you could accidently get different semantics for
assignment in the same program without any warnings. Example:
module X
==============
#include "A.h" // defines class A
extern A a1, a2;
a1 = a2; // uses compiler-generated assignment
module Y
==============
#include "A.h"
extern A a1, a2;
A& operator=(A&, const A&); // missing from module X
a1 = a2; // uses operator function
This sort of thing can't happen with other operators: you can't add a class
object unless a declaration for operator+ is visible, member function or not.
The compiler won't ever create one for you.
2. Simple mistakes that ought to cause compile-time errors could get
turned into valid code by unexpectedly creating temp objects and
assigning to them. For example, suppose we have
T t;
U u;
t = u;
and there is no operator=(T&, U&) but there is a conversion of T to int
and there is an operator=(int&, U&). You could then wind up creating
a temporary int, assigning u to it, and discarding the temp, leaving t
unchanged, and get no complaints from the compiler.
You can get the effect you want, assigning an A to an int, by creating
a function to convert an A to an int.
class A {
...
int to_int();
};
k = a1.to_int(); // ordinary int assignment
Alternatively, you could create an operator int() in class A, but operator
conversion functions are dangerous because they can get called when you
don't want or expect them to be.
Summary: Non-member assignment operators are dangerous and unnecessary.
That is why C++ doesn't support them.
---
Steve Clamage, stephen.clamage@eng.sun.com
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: boukanov@gluon.fi.uib.no (Igor Boukanov)
Date: 1996/12/05 Raw View
Steve Clamage (stephen.clamage@Eng) wrote:
> In article 0412960654310001@platinum.telogy.com, cbreece@telogy.com writes:
> >After looking through a draft of the ANSI spec, and not finding an
> >adequate explanation for having single variable only assignment operator
> >overloading, I thought this news group might be a good place to ask the
> >following.
> >
> >What is wrong with the following, or why is it considered a ``bad
> >thing''. This seems to be more consistent with the rest of the operator
> >rules.
> >
> >class A {
> >public:
> > void operator=(int &value, A &instance) {
> > value = instance.data;
> > }
> >
> > operator=(char* &ptr, A &instance) {
> > ptr = instance.dataPtr;
> > }
> >
> >private:
> > int data;
> > char *dataPtr;
> >}
> >
> I don't see how you would use the member functions you are defining.
I think the idea here is to make possible to define assignment operator
from some class to built-it type and to write:
int i;
i = AInstance;
But in any case this can be done via
class A {
...
int() { return data; }
}
and I do not see here how the code with overloaded operator= can be more
effective than standard construction.
--
Regards, Igor Boukanov.
igor.boukanov@fi.uib.no
http://www.fi.uib.no/~boukanov/
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]