16

On a related question, it has been clarified why C++ is not compatible with C in many aspects. However C++ is still a "hybrid"* language. And unfortunately, many programmers still consider C++ as a "C with streams and built-in strings". That results in really bad written code, that it's neither C++ nor C. IMHO, it would be better if the language/compiler forced to some extent programmers to write more elegant code. So is there a rationale for keeping modern C++ (for instance C++0x and future versions) hybrid?

* By hybrid I mean that it's up to the programmer to decide if he/she will use: standard strings and streams, classes, namespaces other than the default, etc.

sakisk
  • 3,377
  • 2
  • 24
  • 24
  • Are there any existing compiler/IDE settings that could enforce this? – FrustratedWithFormsDesigner Mar 07 '12 at 19:44
  • @FrustratedWithFormsDesigner I'm not aware of any tools that do that. But it would make more sense to write such a tool (compiler, IDE, etc.) if those features were part standard C++. – sakisk Mar 07 '12 at 19:48
  • I know I needed a flag to compile C code as C++, but I doubt its possible to make C++ written like C any different than C++ written like C++ – Ryathal Mar 07 '12 at 19:49
  • 2
    C++'s raison d'etre *is* backwards compatibility and the possibility to use all the dirty tricks that were possible in C. Take that away, and it's just another C#, D or Java clone. If you wanted that, why not just use C#, D or Java? – nikie Mar 08 '12 at 11:26
  • 6
    @nikie: Hahahaha. Because templates, value types, strong references, deterministic destruction, multiple inheritance, speed of execution, low memory usage, those things don't exist at all. – DeadMG Mar 08 '12 at 12:47
  • @DeadMG: Doesn't D have all those things, except for multiple inheritance? (I must admit, I never used it myself) – nikie Mar 08 '12 at 13:43
  • 2
    @nikie: Except D also has abominations like `Object` and binary copying rvalues and language-divined associative arrays (why...) along with other questionable design decisions of it's own. Also, it effectively also has the same GC paradigm as the others, so I'd question it's low memory usage. – DeadMG Mar 09 '12 at 13:16

8 Answers8

26

Yes, there is a strong rationale: C++ code almost always has to call existing C code. The best we can do is make it easy to write good code. There is nothing a language designer can do to make it impossible to write bad code.

kevin cline
  • 33,608
  • 3
  • 71
  • 142
  • 1
    Sure, but since this is only for legacy code why do newer versions of C++ need to remain compatible? Legacy code can still use an older version of C++. – sakisk Mar 07 '12 at 20:09
  • 15
    @faif, in my job I write new C++ code all the time that needs to interface with new C code. It's not just a legacy issue. – Karl Bielefeldt Mar 07 '12 at 20:11
  • 1
    @faif: All Linux and Unix system calls are C functions. And there are a large number of C libraries still under development. – kevin cline Mar 07 '12 at 20:18
  • Agreed, most system calls will be C (this is true for Windows and *nix). For many developers this may never matter. For those working closer to the metal, it means the world. – Michael Brown Mar 07 '12 at 20:47
  • 5
    @faif: newer versions of C++ have to be backwards compatible - not only to support older C code, but also several hundred millions lines of of existing C++ code. If you want something not backward compatible, but better designed, you are free to switch to a language like D. By the way, here is a really good article about the need for backward compatibility of Joel Spolsky: http://www.joelonsoftware.com/items/2008/03/17.html – Doc Brown Mar 07 '12 at 21:17
  • 4
    `The best we can do is make it easy to write good code.` - Are we talking about the same C++? – BlueRaja - Danny Pflughoeft Mar 07 '12 at 21:18
  • 4
    @BlueRaja-DannyPflughoeft: I find it a lot easier to write good code in C++ than in Java or C#. With C++, I can read a class and if all the other classes behave, I know that memory and resources won't be leaked. With Java and C# I can't do that; I have to go inspect the other classes to see if any of them required finalization. C++ templates also let me DRY up code that has to be repeated in Java. – kevin cline Mar 07 '12 at 22:55
  • 1
    @DocBrown: I wouldn't really agree that D is better designed at all. I think that D actually has a pretty bad design. – DeadMG Mar 07 '12 at 22:56
  • 1
    @kevin: The only time classes need to be "finalized" are when dealing with unmanaged resources: files, sockets, etc. This is exactly the same in C++: an unclosed file in C++ will leak the same as in Java and C# *(though it happens less in C#, thanks to the convenience of `using`)*. The only difference is, it happens *more* in C++, thanks to the fact that C++ has to call C code so often *(see @kevin's answer above :) )* – BlueRaja - Danny Pflughoeft Mar 07 '12 at 23:17
  • @BlueRaja-DannyPflughoeft: "The only time..." That's the problem. When reasoning about programming correctness there is only "always", "sometimes", and "never". If even *one* class in a thousand requires finalization, then when inspecting code I have to check *every* class. In C++ files are automatically closed by the stream class destructor, so { ostream f(...); ...; } works perfectly, with no close needed. I don't have to worry about special 'resource' classes; classes either clean up after themselves or they are broken. – kevin cline Mar 13 '12 at 21:34
20

IMHO, it would be better if the language/compiler forced to some extent programmers to write more elegant code.

No, it wouldn't. At all. As a trivial demonstration of why, define elegant, and then I bet that ten people will come on to disagree with you.

Language-enforced coding styles are really, really bad. Not to mention all the legacy code that will be broken.

Notably, the Standard string and stream classes actually suck. std::string has no Unicode support and the worst bloated interface you could possibly imagine. The streams have horrendous overhead and a poor design, even resorting to virtual inheritance, and function pointers, and const char* and uglies like that. I wouldn't penalize anyone for completely replacing both of those classes/class groups with custom ones.

Not using classes and namespaces is fine for whiteboard-style code, and there are many, many libraries which provide functions not in a class. Enforced-class is a really bad idea.

DeadMG
  • 36,794
  • 8
  • 70
  • 139
  • +1 for the somewhat more realistic approach (when shall the "elegant code" talk stop :/ – Rook Mar 07 '12 at 20:06
  • 3
    "Language-enforced coding styles are really, really bad." Can you give some examples? I think that even simple things like Python's enforced code indentation improves code readability. – sakisk Mar 07 '12 at 20:13
  • 3
    I'm not sure if I agree with this. The main reason to use CoffeeScript over JavaScript is because CoffeeScript is designed to enforce the writing of more elegant code. – user16764 Mar 07 '12 at 20:13
  • 4
    Can't agree with this. Some language designs are meant to encourage good practices, and the sprawling, bolted-on nature of much of C++ generally precludes this. In fact, culling the language, keeping the good parts and improving the rest is the principal motivation behind the existence of [C++11](http://en.wikipedia.org/wiki/C%2B%2B11). – Robert Harvey Mar 07 '12 at 20:17
  • @faif Jon Purdy said had some interesting criticism about Python's enforced coding standards. A good quote from the [article](http://evincarofautumn.blogspot.com/2010/09/language-hate.html) is, "writing an ugly program that works is better than writing a beautiful program that does nothing" – Pubby Mar 07 '12 at 20:20
  • @faif: And I bet that there are plenty of people- which happens to include myself- who absolutely hate it. And that's just whitespace, not anything important. – DeadMG Mar 07 '12 at 21:44
  • @RobertHarvey: But none of that is necessarily to do with any of the points the OP raised. The junk parts of C++ do not include not being forced to use classes and namespaces. And, notably, the Standard stream and string classes are, whilst servicable, hardly irreplacable- for example Unicode strings and non-suck I/O. Enforcing their use would be a bad thing. – DeadMG Mar 07 '12 at 21:45
  • 1
    @Pubby: "Writing an ugly program that works is better than writing a beautiful program that does nothing." Sure, I can agree with that. But this article goes way beyond that and seems to argue that ugliness is actually a virtue. And that's just ridiculous. – Mason Wheeler Mar 07 '12 at 22:28
8

C++ is a hybrid not because it allows one to write C-style code, but because it supports several programming paradigms, such as procedural, object-oriented, and generic. C++ does not force you into one way of doing things, and that is its strength, because different problems can be solved more easily using different paradigms.

IMHO, it would be better if the language/compiler forced to some extent programmers to write more elegant code.

Then you first have to define what elegant means. Then you would have to see if your definition of elegant is appropriate to all the problem domains and platforms for which C++ is used. A coding style that is elegant for writing a word processor for Windows might be completely unsuited for writing an embedded system.

Consider writing C++ code to run on a DSP. First, the C++ compiler for that DSP may simply not support certain C++ features, like streams. Second, you are severely constrained by the CPU speed, and possibly memory, so some C++ features may simply kill your performance. For example you may have to avoid virtual functions for the sake of speed. Such considerations would radically change your programming style, compared to what you would use on a PC, and C++ allows that.

To summarize, C++ is a huge and complicated language with lots of features. There are many reasons why any subset of those features may not be applicable to a particular project: speed, portability, compiler support, or even programmer experience and familiarity. For that reason for the language to force the developer to use certain features as opposed to others for any given task is a bad idea. Think of Java, where the language mandates that every function must be a method of a class. There are so many cases when creating a class just to wrap a method is awkward and unnecessary, and yet you have to do it because the language forces you to.

Dima
  • 11,822
  • 3
  • 46
  • 49
  • 1
    Couldn't agree more. I would think that when someone says "C++ is flexible", I would think so because it supports many more paradigms than C does. – prelic Mar 08 '12 at 01:18
5

IMHO, it would be better if the language/compiler forced to some extent programmers to write more elegant code.

No one is forcing anyone to use C++ in the first place. If the language doesn't suit you then use a different one - there are many languages billed as "C++ without C".

The C++ design philosophy is to let the programmer decide. If they want to shoot their self in the foot then let them. This allows many bad things to be done, but also allows a great deal of flexibility. For instance, it is unlikely that Boost could be written in a language like Java as it takes advantage of language features and practices commonly shunned. It's also unlikely that C++ would grow as large as it has today - having access to the vast C library is a huge plus, take it or leave it.

C++'s compatibility with C is definitely one of it's weakest points, but also keep in mind that it's one of its greatest.


I'm going to add in a wonderful quote by Jon Purdy which I feel is extremely relevant:

It all comes down to pragmatism versus elegance, and for me, despite my obsession with precise, beautiful code, writing an ugly program that works is better than writing a beautiful program that does nothing.

Removing the hybrid may improve the elegance, but it hinders the capability.

Pubby
  • 3,290
  • 1
  • 21
  • 26
  • Do you believe that pragmatism and elegance are contradictory? I think that Python, Ruby, and Scala are good examples of languages that are both pragmatic and elegant. – sakisk Mar 07 '12 at 20:51
  • 1
    @faif: No, but *backwards compatibility* and elegance are contradictory. This applies to Python, too (2.x vs. 3.x). – dan04 Mar 08 '12 at 00:41
4

If the committee were to attempt to force people to use (somebody's notion of) a more elegant language, it would probably be ignored. People would continue to do what they want, and compiler vendors would follow the market (but compiler vendors have enough representation on the committee to prevent this).

Much of what you're advocating is really a matter of judgement, based on the problem domain anyway. There are lots of small programs that just don't need (for one example) namespaces. Trying to force me to use a namespace when I'm writing a 30-line text filter would be foolish and arrogant. Even if you decided it would only apply when more than X lines of code, or Y functions, or whatever were involved, it would still generally be counterproductive. Namespaces were designed for a reason, to prevent/cure specific problems. Attempting to force their use in the absence of those problems accomplishes nothing useful for anybody.

At the same time, I think it's worth noting that quite a few people really do spend a lot of time and effort trying to not only enable elegance in C++, but to teach and lead people to use those capabilities to write better code (e.g., many Boost contributors). As such, the people who continue to insist on writing their code as "C with classes" are pretty much ignoring what's out there anyway. I think they'd be just as comfortable ignoring new compilers as they are ignoring everything that's been learned about how to use C++ over the last decade or more (e.g., Modern C++ Design was published 11 years ago now -- but most of the people you're talking about apparently haven't heard of it yet, much less read or understood even its simplest parts).

Jerry Coffin
  • 44,385
  • 5
  • 89
  • 162
2

Your idea constitutes much of the design rationale behind Java. Java forces you to use classes, organize file hierarchy according to package hierarchy, catch exceptions, etc. People still manage to write C-like code in it.

As programmers, we sometimes forget the best solution may not be a technical one. Peer reviews are the best known solution in this case.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
0

C++ has no "one true way"; every approach has strengths and weaknesses. The solution can be written a hundred different ways.

You as a software developer have to decide which approach is best for the task at hand.

Coder
  • 6,958
  • 5
  • 37
  • 49
0

I think the fact that all those things you list are optional creates a potential for more elegance, not less. A feature used unnecessarily is inelegant in my eyes.

The problems that we need to solve using programming are very dissimilar.
Some are solved well using OO principles (e.g. GUIs), some lend themselves better to a purely functional treatment (e.g. numerical stuff), while some are best expressed in a low-level "close to the silicon" language.

Plenty of software needs to solve subproblems that are solved best in any one of those ways. Forcing the solution into a specific form will only lead to code that is less fit to its purpose (you might even say "less elegant").

This is why the hybrid-ness of C++ is a good thing - it lets us solve a vast array of problems in a way that suits the problem, not the current dogma.
Of course it can be misused - whenever you have a flexible thing there's a risk of you bending it in a bad way - but elegance comes from careful thought and experience, not from adherence to whatever is the fad du jour.

molbdnilo
  • 239
  • 1
  • 4