Hi Cymric
Cymric wrote:
...
I avoid function name overloading like the plague: the implicit argument type promotion rules to test whether two functions are equal are a nightmare. The feature is useful in a few select cases, but in my experience too often led to obfuscation rather than clarity.
I agree with you that overloading can be awkward, but if your's sensible with it it can be very useful.
Generally, I only overload function names for custom types rather than the builtin ones, unless I'm damn sure its a good idea.
As you probably know, the classic ambiguities are caused by things like
// plain bad overload example ;-)
// return types not part of overload resoulution
double func(double x, double y);
int func(int x, int y);
int ix = 1, iy = 3;
double dx = 1, dy = 3;
double z;
z = func(ix, iy); // ok
z = func(dx, dy); // ok
z = func(ix, dy); // Promotion ix to double (?)
z = func(dx, iy); // Promotion iy to double (?)
z = func(1, 3); // Which func() is used?
As you point out, it can get real messy ;-)
To be totally unambiguous, you need to write stuff like
double z = func((double)ix, dy);
double z = func(ix, (int)iy);
double z = func(1.0, 3.0); // uses func(double, double)
double z = func((int)1, (int)3); // uses func(int, int)
Yuk! All of which is not nice for readability.
Now, what I would do is something like this
// in reality, I'd use a class, but for sake of a
// no-classes C-style code example
typedef struct {
double real;
double imaginary;
} complex_t;
// function name overloading and references...
complex_t func(complex_t& x, complex_t& y);
double func(double x, double y);
It would be pretty difficult to muddle up the above two functions.
References... Now there's a feature I'd love to have in C. Although I also believe that every C(++)-programmer should experience the exquisite emotions caused by an oh-so-subtle pointer bug at least once in their lives.
:-) Agreed. When I first started using C, I had to chase a few obscure pointer bugs. Lovely!
References are real handy and often get used to avoid passing/returning large objects. But you do have to be careful when returning references - a lot of problems are caused by returning references to objects that only exist within the scope of the function in which they were created. Just as bad as any pointer bug :-D
Also, unlike references in Java, once assigned, the reference can't be reassigned - the reference and the object referenced are as one ;-)
But despite the better features, it has its share of problems too: the syntax is complex (although not unbearably so), it has no garbage collection and still has you managing memory by yourself, and quite a number of others, which may not directly affect a programmer working on his own, but will when working in a team.
Well, C has no garbage collection either. It's a double edged sword anyhow. Garbage collection is not all that it's cracked up to be IM (not so?) HO.
Incidentally, there are plenty of garbage collectors available for C++, it's just not part of the standard library (some implementations do come with them however).
The difficulty in their implemtation comes down to the fact that C++ is not pure OOP and things like pointers make garbage collection tricky.
In java for example, there are no pointers and every class is ultimately derived from 'Object' so it's possible to track every instance of every class and determine when an object has gone out of scope and can be recycled. But the convenience does not come for free either.
In most C++ garbage collectors, you have to write your class around whatever 'collectable' service class the garbage collector implementation provides.
Maybe I'm old school but I prefer manual memory management. Best clean up after yourself, so my mum taught me ;-)
When it comes to large scale, multi-person programming, features like namespaces are ideal.
You can write solid and tidy code with C++; just keep in mind it is not a miracle cure to every programming problem, OO or otherwise.
Well, I never said it was a miracle cure ;-)
But it is quite useful nontheless.