5 operator overloading is fun because it makes programs
6 more interesting as it can give new meanings to strange
7 symbols (most of which are unused for structures), and
8 make your code more cryptic and impressive.
14 In this example we will overload '~' for pointers to
15 free the memory and '!!' for strings to print a message
16 on stderr. These two operators are by default invalid
17 on pointer operands ('!!' is a new operator of lwc which
18 toggles boolean values prefix or postfix. after the introduction
19 of the postfix() '!!' is redundant and can be
20 used as a free operator for overloading).
22 void operator ~ (void *p)
27 void operator !! (char *c)
29 fprintf (stderr, "%s\n", c);
36 char *x = malloc (100);
40 ~(int)x; // force complement
44 We can extend this example, overloading the binary comma operator
45 to make an experimental and fun output facility subsystem:
51 FILE* operator, (FILE *f, int i)
57 FILE* operator, (FILE *f, void *p)
63 FILE *operator, (FILE *f, char *s)
75 stdout, "The values are: ", i, " and ", (void*)p, " [", p, "]\n";
79 ________________________
80 1. Operators for objects
81 ~~~~~~~~~~~~~~~~~~~~~~~~
83 operators for objects can be defined as member functions or
84 global functions where the first argument is a structure.
85 The difference is that member functions are inherited and
86 can be virtual. Apart from that the two forms are the same.
88 From the 46 operators of C, 43 do not make sense for structures.
89 From these, 26 do not make sense even if the operand is a
90 pointer to a structure. Unlike c++, in lwc operator overloading
91 works for structures and *pointers to structures*.
97 The operators that make sense only with arithmetic operands are:
100 binary: * / % | ^ & , *= /= %= ^= |= &= << >> <<= >>=
103 Overloading those is safe and the overloaded action will be used
104 even if the operands are *pointers to structures*. For example:
108 void operator + () { i = 0; }
109 void operator * (int j); { i += j; }
110 void operator () (int x, int y) { i = x - y; }
128 In all the cases, the overload functions will be called.
134 The operators below make sense if the operand is a pointer
135 to an object and so lwc will not use operator overloading in
136 this case. To insist of overloading, the operator function can
137 be forced by using "->operator".
140 binary: + - > < >= <= == != && || += -=
147 void operator * () { f = 0; }
148 bool operator == (A a) { return fabs (a.f - f) < 0.001; }
149 float operator + (float x) { return f + x; }
150 int operator + (int x) { return f + x; }
151 A operator - (A a) { A r; r.f = f - a.f; return r; }
152 A operator + (A a) { A r; r.f = f + a.f; return r; }
157 A a, *ap = &a, b, *bp = &b;
167 *ap; // default action: pointer indirection
168 ap == bp; // default action: comparison
169 ap + 1; // default action: ptr arithmetic
170 ap - bp; // default action: ptr arithmetic
172 // pointers + forced operator
174 ap ->== bp; // overload
175 ap ->+ 1; // overload
176 ap ->- bp; // overload
178 // pointers + invalid expressions
179 ap + 1.0; // overload: makes no sense ptr + float!
180 ap == b; // overload: makes no sense ptr == obj!
181 ap + bp; // overload: makes no sense ptr + ptr!
183 ap ->+ 1.0; // overload for both reasons
186 As it can be seen, lwc will not use the overloaded function if:
187 the base operand is a pointer && the action is not forced by
188 enclosing the operator in parentheses && the operation is valid.
190 Whether operations are valid is checked for:
191 + += : valid if other operand int
192 - -= : valid if other operand int or ptr
195 > < : valid if other operand not float and not structure
196 && || : always valid unless other operand a structure
199 1.c Postfix ++ -- !! (new in lwc 1.1)
202 The keyword 'postfix' must be used after 'operator'. Example:
206 int operator ++ () { return ++i; }
207 int operator postfix ++ () { return i++; }
220 This is also an unsafe operator as the 1b section. What is special
221 is how to force operator overloading on the operator.
225 float &operator [] (int i) { return f [i]; }
232 a [12] = 3.14; // overload
233 ap [12]; // default action: ptr arithmetic, result 'struct A'
234 ap ->[12] = 3.14; // overload
235 ap [12][12] = 1.41; // overload on 12th element of ap array
239 1e. Very Unsafe operator
240 ~~~~~~~~~~~~~~~~~~~~~~~~
242 This is the '=' operator. Normally, it makes sense in all cases.
243 If overloaded, it will always use the overloaded version for structures
244 and the default action for pointers. So this works exactly like the
245 unsafe operators. Also note that this is not a copy constructor:
246 it is not invoked in declaration initializations.
248 The second operator is '->' which works ONLY for objects. See "5.0.new-in-.."
253 Non-overloadable operators at the moment are:
255 unary: & (cast) sizeof delete new localloc
258 There are reasons for not overloading each of these.
259 Send proposals to the mailing list.
262 * 1g. New in lwc-1.0 *
263 ~~~~~~~~~~~~~~~~~~~~~~
264 As an exception to whether overloading on unsafe operators is permitted,
265 if the first operand is 'this' overloading takes place. For example:
268 int &operator [] (int i) {
271 int &operator += (int i) {
275 this [12] = this [13]; // operator overload!
276 this += 24; // overload
277 this += this [12]; // overload
278 (A*) this += 12; // default action
279 ((A*)this) [1] = 3; // default action
283 This happens for all the dangerous operators except:
284 unary * and binary == and !=
286 _________________________
287 2. An interesting example
288 ~~~~~~~~~~~~~~~~~~~~~~~~~
290 An interesting example where we implement our own complex
300 ctor (float r, float i) {
315 A& operator = (A a) {
320 A& operator += (A a) {
325 A& operator *= (float f) {
330 void operator !! () {
331 printf ("[%.3f %.3f]\n", re, im);
337 A c1 (1, 2), c2 (3, -1);
342 c5 = c4 + (cc += c = c1 + c2) + c4;
346 !!c1, !!c2, !!c, !!cc;
350 The interesting thing demonstated in this program is when to return a
351 reference and when to return an object. A reference should be returned
352 when the object is modified and the result is an-lvalue. On the other
353 hand when the operation is a temporary value, a temporary object should
356 A problem with lwc at the moment is that it will call the destructor of
357 the object of, say, function '-' while it will not call the constructor
358 of the temporary object where the return value will be placed. In simple
359 words, we can't use this technique yet on object that allocate/free memory
360 at their construction/destruction, or do other critical things there.
363 ______________________________________
364 3. lwc && structure by reference calls
365 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367 In lwc, structures are always passed by reference. Moreover, as explained
368 in the tutorial, both a structure and a pointer to a structure can be
369 passed to such reference arguments. The lwc preprocessor will make the
370 necessary conversions. As a result, it is possible that the one operand
371 will be an object and the other a pointer to an object. It will work.
374 void operator == (A);