Some people have mentioned portability, but in this day, the portability of C++ isn't much of an issue (it runs on anything GCC runs on, which is essentially anything). However, portability is more than just architecture-to-architecture or OS-to-OS. In the case of C++, it includes compiler-to-compiler.
Let's discuss ABI, or Application Binary Interface. This basically means "how your code translates into assembly." In C, when you write:
int dostuff(const char *src, char *dest);
You know that you're making a symbol in your object file called _dostuff
(C global names are all prefixed by an underscore in the resultant assembly). But in C++, when you write this:
int dostuff(const char *src, char *dest);
int dostuff(const char *src, char *dest, size_t len);
Or even:
int dostuff(std::string src, std::string dest);
All bets are instantly off. You now have two distinct functions, and the compiler has to make each, and has to give each a unique name. So C++ allows (where I believe C doesn't) name mangling, which means those two functions might get translated to _dostuff_cp_cp
and _dostuff_cp_cp_s
(so that each version of the function that takes a different number of arguments has a different name).
The problem with this is (and I consider this a huge mistake, even though it's not the only problem with cross-compiler portability in C++) that the C++ standard left the details of how to mangle these names up to the compiler. So while one C++ compiler may do that, another may do _cp_cp_s_dostuff
, and yet another may do _dostuff_my_compiler_is_teh_coolest_char_ptr_char_ptr_size_t
. The problem is exacerbated (always find a way to sneak this word into anything you say or write) by the fact that you have to mangle names for more than just overloaded functions - what about methods and namespaces and method overloading and operator overloading and... (the list goes on). There is only one standard way to ensure that your function's name is actually what you expect it to be in C++:
extern "C" int dostuff(const char *src, char *dest);
Many applications need to have (or at least find it very useful to have) a standard ABI provided by C. Apache, for example, couldn't be nearly as cross-platform and easily extensible if it was in C++ - you'd have to account for the name mangling of a particular compiler (and a particular compiler version - GCC has changed a few times in its history) or require that everyone use the same compiler universally - which means that, every time you upgrade your C++ compiler with a backwards incompatible name-mangling scheme, you have to recompile all your C++ programs.
This post turned into something of a monster, but I think it illustrates a good point, and I'm too tired to try to trim it down.