|
Okay. Let's get off on the right foot. I don't think C++ is all bad. I might even go so far as to say that it has some pretty good points, such as templates. But for the most part, it is all pretty mediocre.
I wonder why it even caught on in the first place? I mean, it isn't like C++ was a magnificent invention of Object Orientation created in a vacuum; other object oriented languages existed before it by quite sometime and Objective-C--which is an overall better direct competitor--was created about the same time. So what went wrong?
Now I'm not going to spend my time here on the normal rants, such as the ever popular dynamic-typing vs. static-typing argument. I have used both extensively, am comfortable with both, and see the advantages and disadvantages to both. (For the record, I like Objective-C's version: static most of the time, but can be dynamic when you need it.) I'm not even going to bother you about the normal messiness complaints, like the zillion places you have to use the const keyword or that virtual should have been the default state for object functions like every other object oriented langauge I know. No, I'm going to hone down to something more specific--Indeed, I'm going to hone down to my biggest peeve, neglecting the zillion other peeves I have with this language.
Well, I'll hold off on my biggest peeve for just one moment so that I can lead you along my thinking.
Usually, in the span of less than a week, I can learn a programming language well enough to design and write code in a style that matches those who are native users of the language. I may not be some genius with it--I mean, I still have to look up API calls and syntax all the time--but I've got my brain wrapped around the intent of the language, and the way one is meant to use it. Indeed, I have done this with many languages, including java, Objective-C, Ruby, PHP, and Perl. C++, however, always seemed to elude me. I easily got good enough to write code that gets the job done, but I'd always feel like I hacked my way through it instead of designing and implementing an elegant solution.
Of course, I'm not one to back down from a challenge. Whenever I feel like I don't understand something, I feel compelled to learn until I do understand it. I also recognize that one's natural instinct when they try to learn something and not understand it: we naturally seem to hate it. So, between my natural curiosity, and the fear that my dislike of C++ was actually because of my own ignorance, I bought more books on C++ and started hitting up some programmer friends to get their input.
What I found astonished me. As I learned more C++, read more books, talked to more people, and saw more example code, I realized that there were many different styles to writing a C++ program. I'm not talking about code formatting (e.g. where one puts their curly braces or whether they name class variables with underscores as their frist character), I'm talking gross differences like my biggest peeve of all, call by pointer versus call by reference.
While learning C++, every book would talk about call by reference, like void function( Obj & o ), and call by pointer, like void function( Obj * o ). These books, would, however, refuse to address when you should use which one and why. For a new learner of the language that is concerned not with just getting things done, but with getting things done right, this is very confusing. To complicate matters even more, it becomes apparent that both methods let you accomplish exactly the sam thing, it is just that the notation with one is considered to be cleaner than the other. (For the record, I never thought pointer syntax was so complciated to warrant inventing a second way of doing things just to avoid it).
Anyway, when I originally learned C++ was back during my second year of college (before the 1998 C++ standard). I had gotten my hands on BeOS and it immediately became my primary operating system. Now, as some of you may know, BeOS used C++ as its language of choice. Me, being a programmer type, wanted to write applications for BeOS. So, naturally, I went out and bought a book on C++. As mentioned, I was comfortable with everything for the most part, but, as expected, I found the use of call by reference and call by pointer confusing. I could use one or the other, but I didn't understand when I was supposed to. Well, to make a long story short, BeOS used a call by pointer based API (I never even saw a single call by reference function in the code), and so I ignored call by reference figuring most people never were sensible enough to never use it.
It wasn't until several years later, when I decided to learn operator overloading and exceptions, that I realized that the "native" functions of C++ all used call by reference. This perplexed me. So I asked my genius programmer friend (who is now off doing great things and doesn't think anything of it) when to use which. His answer was simple: you can use either one you want in your entire program, except for with exceptions and operator overloading.
Ah! A revelation! C++ wasn't designed to have one good way of doing something. It was designed to have two different ways of doing the same thing when only one was enough!
Of course, I then decided to revise my original thought on references: I could ignore call by reference, figuring that I'd only have to use it when I collide with the design commitee's odd way of thinking.
This was short lived. In the years folowing the 1998 C++ ANSI standard, I decided to bring myself up to date on the latest advances. Of specific interest was the standard libraries that provided basic data structures. To my horror, they too used call by reference! I then had to revise my thinking again: I should probably use call by reference whenver possible, because everyone else wasn't sensible enough to ignore it.
This gave rise to another problem however: If I write my programs to use dynamic allocation extensively (because this really is the best way to deal with a large program in my opinion), that means I have to allocate by pointer and, naturally, I should be making my instance variables be pointers. (I should also mention that I like using pointers as instance variables has a lot of other advantages that don't need to be mentioned here). This, of course, means that now I'm having to mix pointers and non-pointers all the time (especially in object functions, which makes for much messier notation (and hence harder to read code) than if we had just stuck with the pointers and pointer syntax in the first place!
I can, however, take much consolation in the fact that despite its popularity, more and more programmers are becoming fed up with C++. One can easily see this by looking at the proliferation of new languages invented specifically to replace C++, such as Java and C#. Furthermore, every major operating system, other than Linux, is pushing a clean C++ alternative as its language for modern application design--Microsoft with C# and Apple with Objective-C.
I take the most consolation of all, however, in the fact that none of these other languages try to have the duality of call by reference and call by pointer. Although different languages may use one or the other for function calls, they all handle the classes as pointers in a clean and efficient manor both in notation and in concept.
It looks like C++ is quickly headed to obscurity, which is probably where it should have been all along.
(c)2005, Jeff Reinecke. |