Thursday, January 9, 2014

C++ vs. Java

I'm not trying to start any sort of religious war here; I'm writing this because I've been programming in C++ for the past six or seven months after more than three years of professional Java (and more than ten years in personal projects). So I feel like I have an informed opinion.

Unfortunately, my opinion may incense some: Programming in C++ after being used to Java is like slogging through mud. And here's why:

  • Auto-completion. Eclipse does it badly for C++, and neither Emacs nor Vim will do it automatically. I'm sure I could set it up, but it still would not be as good at it as Java in Eclipse. I am unaware of other choices (don't even try to suggest Visual Studio; nobody uses Windows for real software development).
  • Header files. I need to write one of these, with ancient C include guards around it, for almost every interesting piece of code.
  • Prototypes. I need to repeat myself. I need to repeat myself. It's 2014!
  • Surprisingly, flexibility of where classes can be written. In Java, if I want to write a new class, it pretty much always gets its own new file, and the name of the file is the name of the class. But in C++? It can go anywhere, including in whatever file I'm writing when I decide I want it. And there is no naming requirement for linking headers with source files.
  • Threading is a special case in C++.
  • Memory management. I wish there were more options in Java (stack allocation, for example), but it requires too much extra effort in C++, including destructors. Rust has some interesting ideas around this, but it adds to the number of indirect reference types.
  • Boilerplate code. Java has some, certainly, but C++ has so much more. Refer back to header files and prototypes. And memory management (std::unique_ptr<actualtype> anyone?). And how many times have you written "virtual ~ClassName() {}"? Or, even worse, "virtual ~ClassName();" in a header and "ClassName::~ClassName() {}" (with its multiple instances of repetition) in a source file?
  • Namespaces. Not only do I need to include something, but I still need to either type out the namespace every time, or add a using directive. And then we get back to problems with header files; can't put a using directive there without screwing everything up when someone includes the header. Oh, and they're not implicit based on the file path, so at a minimum I'll need to write each new one twice. Is it obvious yet how much I hate to repeat myself?

But, to be fair, there are a few areas where Java is severely lacking:

  • Memory  management. It is really hard to write a no-gc Java program, and it may be impossible without abusing class fields and sacrificing immutable types. Stack allocation would go a long way here. Seriously. Why is this still missing? You could probably do it with a single new keyword, or by overloading the meaning of one of the operators.
  • Const. I really miss this in Java. Really, really </Shrek voice>.
  • Templates. C++ mostly got this right with weak typing. Java requires strong typing, and you can't really specialize. And they're erased, so you're doubly... Triply screwed.
  • Macros and conditional compilation. Less important (to me) than anything else here, but sometimes I really wish I could define a macro that would evaluate into some repetitive multi-line construct that, instead, I need to type out (usually with the help of block-selection and editor macros). Oh, look at that, more repetition...

It's entirely possible that most of this boils down to how expressive the language is. Either way, maybe it's time to learn Go...

No comments: