110

Suppose I am limited to use C++ by the environment in the project. Is it good to prevent the use of some language features that C++ has but Java doesn't have (e.g.: multiple inheritance, operator overloading)?

I think the reasons are:

  1. As Java is newer than C++, if Java doesn't provide a feature that C++ has, it means that the feature is not good, so we should avoid using it.
  2. C++ code with C++ specific features (e.g.: friend functions, multiple inheritance) can only be maintained or reviewed by C++ programmers, but if we just write C++ like Java (without C++ language specific feature), the code can be maintained or reviewed by both C++ and Java programmers.
  3. You may be asked to convert the code to Java some day
  4. Code without C++ specific features is usually more maintainable
  5. Every C++ language specific feature (e.g.: multiple inheritance) should have alternatives to be implemented in Java. If it doesn't, that means the design pattern or code architecture is problematic.

Is that true?

15
  • 7
    If you look at your suggestions you are talking about creating a coding standard. The fact that you are creating and following a standard is actually what is going to increase the maintainability.
    – Brandin
    Commented Jan 25, 2016 at 10:31
  • 65
    Should Java code also be restricted to features, which are also found in C++ language? So don't use for example Java volatile, package-private class member access, reflection/introspection, finally-blocks, checked exceptions, and so on? The whole question kind of doesn't make much sense... C++ and Java are superficially similar, but ultimately very different languages.
    – hyde
    Commented Jan 25, 2016 at 13:09
  • 5
    How are languages to evolve if people are unwilling to use new features? The purpose of the new features is to make your life easier by solving common problems. If users do not use new features, then there's no motivation for anyone to implement them.
    – Matthew
    Commented Jan 25, 2016 at 14:09
  • 74
    If you want Java, use Java. If you use C++, use C++, not some horrible, twisted imitation of Java with C++ syntax. Using C++ but restricting yourself to Java's feature set gives you the worst of both worlds. Commented Jan 25, 2016 at 17:06
  • 11
    You'd be surprised by how fast the differences will bite you (and hard). SomeObject a = previousObject;does very different things in Java and C++. In Java it copies a reference, while in C++ it copies the object. In Java, modifications to a would also affect the previous object. In C++, you have two separate objects. Commented Jan 26, 2016 at 11:18

13 Answers 13

303

No. This is woefully and terribly misguided.

  • Java features are not somehow better than C++ features, especially in a vacuum.
  • If your programmers don't know how to use a feature, train or hire better developers; limiting your developers to the worst of your team is a quick and easy way to lose your good developers.
  • YAGNI. Solve your actual problem today, not the ghost of some future problem.
3
  • 6
    There was a question recently about developers reviewing code in a language they don't normally write. I think the wisdom there applies here: a good developer will spot many basic mistakes in just about any language, but each language has so many gotchyas that maximum benefit is achieved when in-language developers do the review. This is even true if your C++ is "Java features only".
    – corsiKa
    Commented Jan 25, 2016 at 18:49
  • 5
    +1 In addition to your second point. The OP should take the time to read about "C++ Best Practices" to decide which features they should use. My last information about C++ are that friend functions and multiple inheritance are considered Bad Practices. Things like Templates and Operator Overloading are IMHO good practices if you use them wisely.
    – some_coder
    Commented Jan 26, 2016 at 7:54
  • 4
    @some_coder: It's all a matter of knowing when, and where. When I do policy-based programming, I inherit from the (possibly multiple) policy classes to extend the structure of my host class with the members those policy classes require to function. It's just how it works. Also, operator<<( ostream &, T const & ) is usually implemented via friend. That's the problem with blanket statements about what's a good language feature and what's a bad one: They are good advice, except when they aren't...
    – DevSolar
    Commented Jan 29, 2016 at 16:40
143

Just because the syntax seems similar on the surface doesn't mean that the two languages are compatible.

1, 4 and 5 are really the same question:

Now, I'm no fan of C++, but saying "Code without C++ specific features is usually more maintainable" is just ridiculous - do you really believe that Java got everything right, and took all the good features while ignoring all the bad ones? Do you really believe there is something that's universaly a "bad" or "good" feature? If there is, why don't we have one language that is purely good? And no, Java certainly isn't that language. Does that mean that Java and C++ are useless? Of course not.

What if your leaders decide that you're going to port to C#, rather than Java? Not only does C# support overriding operators, but it's also the default - if you're going to require people to use e.g. obj.Equals(obj2) instead of obj == obj2, people are going to make mistakes all the time. Even if you keep only to the common features of the two languages, there are different expectations, a different culture. If you do something like if (myField == null) in C++, people are going to see you're a novice immediately. If you use if (null == myField) in C#, people are going to see you're not really C# native yet - the reasons C developers learned to use the "flipped" variant no longer exists in C#.

Using your logic, we should have stuck with machine code or assembly or COBOL, because why ever change to something like Pascal, when it just adds new features that your programmers will have to learn? Why would we ever use something like SQL, when it doesn't even have loops? Why would we ever use something else than SQL, when SQL doesn't have loops and X does?

C++ code certainly cannot be maintained by Java programmers. I can't understand where you got this idea - what exactly remains when you limit C++ to only the features that work exactly the same as in Java? You're not even going to get method calls - not even function calls. Again, just because both langauges use curly braces, doesn't mean that the languages are in any way interchangeable.

Converting Java-like C++ code is going to be extremely error prone no matter what you do. There's just too many differences. If you care about having to rewrite your application in a different language, think about reasonable ways to modularize everything, so that you can replace the parts without breaking the whole. But in the end, YAGNI - no matter what you do, there's going to be a significant cost to making your code "ready to convert to Java". That's time that's very likely better spent on adding or improving your features.

We use different languages because they give us a different set of tools to solve problems. If you need executables that work "everywhere", go with Java. If you want code that compiles "everywhere", C++ works fine. If you want code that's easy to understand and parse, go with LISP or whatever. But I can tell you one thing - writing code in one language as if you were writing it in another is always a mistake, and you will suffer. Not to mention that when you actually hire a C++ guy, he's going to run the second he sees that "Java-ish compatible" code. And... the Java guy is going to do the same. You know, even "knowing" both C++ and Java, I'd run like hell :)

I actually had to work on (plain) C code written by a Pascal developer who seemed to think like you do. He used #defines to redefine C to look and feel more like Pascal, complete with things like "BEGIN translates to {". The result was rather predictable - code that neither C nor Pascal developers can understand, and full of bugs that were a result of the leaking "abstraction" of Pascal on top of C. And Pascal and C are almost identical from today's point of view. Even going C <-> C++ is much more of a difference, and that's still peanuts to something like C++ <-> Java.

26
  • 11
    "If you want code that's easy to understand and parse, go with LISP or whatever." I wouldn't agree with that. Lisp is trivial to parse, but precisely because of this--because it was created in a time when the knowledge of parsers and the principles behind building them effectively was still in its infancy, and so they punted and went with the most ridiculously simplistic thing that could possibly work--you don't get a lot of the syntactic benefits of modern languages. So it's easy to parse, but not at all easy to understand. There's a reason people call it "Lost In Superfluous Parentheses." Commented Jan 25, 2016 at 21:58
  • 9
    @MasonWheeler That's a matter of taste - C programmers called it that, not LISPers :P . Count the parentheses - there's about as many as in your typical C++ program. The real difference is their position (myFunc() versus (myFunc)), and that has a very good reason. LISP-based languages are still very popular, especially with math/physics people. The main thing is really that LISPy languages are very unfamiliar to modern C-style programmers - but that's hardly a reason to ignore it. Scheme, Clojure, and to an extent the ML-based languages (OCaml, F#...) are very LISPy indeed.
    – Luaan
    Commented Jan 26, 2016 at 8:01
  • 6
    @Luaan I can tell you for certain that LISP is NOT popular in physics. The two dominant languages in the field are FORTRAN and C++. FORTRAN is 'popular' because so many old codes were written in it, but almost all the new programs are written in C++. As a research physicist, I have not once encountered or even heard of a LISP program. Not to say they don't exist, but the languages is definitely not popular. Commented Jan 26, 2016 at 19:13
  • 4
    @Luaan We may or may not need more software developers. We definitely don't need more CS graduates. That's like saying "we need more structural engineers, so we need more theoretical physics graduates."
    – mrr
    Commented Jan 26, 2016 at 20:36
  • 4
    @user1717828 It's to avoid the delightful effects of mistyping if (myField == null) as if (myField = null), which will compile just fine C/C++, but probably not do what you intended. On the other hand, if (null = myField) will throw an error, since you can't assign to a constant.
    – Wlerin
    Commented Jan 27, 2016 at 5:58
93

I will answer your questions in order.

  1. If Java doesn't provide a feature that C++ has, it means that the feature is not good, so we should prevent using it.

Yes, any feature not present in Java is anathema on the hard drive. It must be burned from your code base. Those who do not obey will be scrounged, their souls used to placate the RAID gods.

  1. C++ code with C++ specific features (e.g.: friend functions, multiple inheritance) can only be maintained or reviewed by C++ programmers, but if we just write C++ like Java (without C++ language specific feature), the code can be maintained or reviewed by both C++ and Java programmers.

When in doubt, write code for the least competent member of your team. Code is read far more often than it is written, and code that is as clever as you can write is too clever to read. Code reviews that your front desk staff won't understand should be rejected. To help, teach them how to program in visual basic 2.0 over the weekend, then emulate their coding style in whatever language you are using.

  1. You may be asked to convert the code to Java some day

True! But why stop at Java? You may be asked to convert the code to basic, assembler and/or perl one day. As there are perl interpreters in every language out there, simply write your program as a long perl string, and marshal arguments into it in the language of choice.

Now when you need to change languages, simply rewrite the code wrapping the perl string.

  1. Code without C++ specific features is usually more maintainable

It is true that code that uses less features is easier to maintain. And as all languages are equivalent to a Turing Machine, and a Turing Machine has the fewest features of any programming language, have the above perl interpreter actually run a Turing Machine (tape and all) that solves your problem.

  1. Every C++ language specific feature (e.g.: multiple inheritance) should have alternatives to be implemented in Java. If it doesn't, that means the design pattern or code architecture is problematic.

The C++ language specific features actually have a valuable use. As they are not Java, they are anathema, and those who use it can be branded heretics. If C++ did not have those language features, you would not be able to find those you need to sacrifice. C++ language features solve problems!


Look, C++ and Java have a different set of capabilities. Programming in the intersection of C++ and Java results in code that has thrown away most of the advantages of both languages.

Java was developed partially as a reaction to some abuse of C++ features. This doesn't mean that the reaction was justified, especially years afterwards when the features have matured.

You can do horrible things with operator overloading; but no language can prevent horrible code from being written in the language, unless it stops all code from being written in the language.

And you can also do very elegant things with operator overloading. Simple things, like a complex number or matrix class that works like complex number or a matrix.

Caution about using C++ features not available in Java should be viewed with caution. Just because your current set of developers at their current skill level don't understand a feature doesn't mean it should never be used; at the same time, just because you can use a feature, doesn't mean you should. However, in a Java-heavy shop, odds are resistance will be stronger than it should be against non-Java-esque features.

Conversion of code between languages is best done with a rewrite, no matter how structurally similar they are. Any attempt to do so without such a rewrite is going to fail miserably.

Many C++ specific features are wonders for maintenance. Type erasure (like std::function) lets you decouple hierarchies, which reduces dependencies. Smart pointers and deterministic lifetimes and RAII reduce runtime surprises, and move resource boilerplate out of the way. Heavy static type-checks mean that code fails to compile, instead of failing to work. Mix-ins reduce code duplication. ADL allows ad-hoc independent extension of interfaces between type hierarchies. Lambda lets you write code next to where it is used. Forwarding and moving reduce copies, and make functional style (side-effect-free) programming efficient. Operator overloading reduces line noise, and makes code look more like the math it is modelling.

Beware the Turing Tar pit. You can implement everything in any language (including a raw Turing Machine with Tape), but that doesn't mean you should. Emulating C++ features using Java-esque constructs in C++ is a horrible idea; it will result in unmaintainable code that nobody can read or understand.

You can take inspiration from Java designs and port them over to C++. I am a great fan of taking Python language features and implementing them in C++, because I like the syntax. But that doesn't mean I write my class methods as static methods taking an explicit self, then write a wrapper that forwards the non-static method call to it.

Modern C++ is not all that much like the language Java emulated and rejected. Don't get locked down by one language's features; there is no "one true language". Learn about new languages and their features, and absorb their distinctiveness.

9
  • 1
    -1, long-winded and unclear.
    – djechlin
    Commented Jan 25, 2016 at 23:05
  • 4
    -1 argumentative, straw-man argument
    – user949300
    Commented Jan 26, 2016 at 3:08
  • 29
    +1, proper deconstruction of the questions asked and I laughed :)
    – cat
    Commented Jan 26, 2016 at 15:15
  • 11
    +1. Hilarious but keeps the point. Highly clear for people actually reading it. Commented Jan 28, 2016 at 3:32
  • 14
    "Programming in the intersection of C++ and Java results in code that has thrown away most of the advantages of both languages." Hit the nail on the head! +1
    – Ajedi32
    Commented Jan 28, 2016 at 20:39
55

I'm just gonna answer your reasons:

  1. I don't understand how you come to that conclusion. Different languages have different features. Depends on scope, architecture of language, sometimes preferences of creators and many more reasons. Some features of a language may be bad, but your generalization is plain wrong IMHO.
  2. Writing C++ just like Java may lead to worse code. E.g. nowadays with C++11 I avoid using new/delete, but use shared pointers. In your scenario I would rely only on new/delete. If your programmers understand only Java, train them or hire better ones.
  3. Is that likely gonna happen? Why don't you write in Java in the first place? I think rewriting programs from scratch in a new language is generally a bad idea and you would need a really good justification for such a risk.
  4. This is just an assumption.
  5. Depends IMHO highly on your scenario or use case.
5
  • 27
    And Java-Programmers wouldn't use delete either. Commented Jan 25, 2016 at 21:27
  • 8
    I've had to fix memory leaks caused by Java programmers not knowing about delete. From what I recall, in at least one of those cases, dynamic allocation (new) wasn't needed either.
    – Soron
    Commented Jan 25, 2016 at 23:53
  • 16
    @EthanKaminski Yeah, that's how you can easily spot a C++ newbie, especially someone who comes from a Java background or similar. Stop using new for everything, dammit!
    – Luaan
    Commented Jan 26, 2016 at 8:02
  • 1
    @PaŭloEbermann Yes, even worse.
    – Simon
    Commented Jan 26, 2016 at 9:12
  • 1
    "In your scenario I would rely only on new/delete" -- funny, I would have thought that a "Java(like)-features only" C++ idiom would be to exclusively use make_shared. Commented Jan 27, 2016 at 16:18
26

Java has features that C++ doesn't, like a built-in, fast, reliable garbage collector, a single-root object hierarchy, and powerful introspection.

Java's other features are designed to work together with the Java-exclusive features, and many of Java's omissions of C++ features are possible because the new features make up for the lack. For example, Java doesn't have stack-allocated objects with deterministic destructors, but has finally blocks (and try-with-resources since Java 7) and the garbage collector to make up for this lack.

C++ doesn't have finally blocks or garbage collection. If you don't use destructors because they don't exist in Java (I don't count finalizers), you're on the C level of resource management (i.e. all manual), except that you can't even group your cleanup into a cleanup block that you goto to, because Java doesn't have goto either. Do you really think that improves maintainability?

Java has an overarching object hierarchy where every class ultimately derives from Object, and the few primitive types can be auto-boxed into such classes too. This enables writing containers of objects once, to hold pointers to Object. Java 5 introduced generics, which get rid of the casts such containers necessitate, but still compile down to pretty much the same code.

C++ doesn't have such a hierarchy. To facilitate the writing of containers that work for multiple types, you use templates, which are blueprints that are instantiated by the compiler as necessary for different types. Will you forbid the use of templates (and macros) and go the C route of either writing the same container code over and over for different types, or using void pointers? (Wait, Java doesn't have void pointers!) Are you sure this would increase maintainability?

A decent language has a multitude of features that are designed to work together. By forbidding features from language A because language B doesn't have them, you are crippling language A, because you are not at the same time adding features from B that make B a coherent whole.

That's not to say that you must not restrict the allowed features of C++. C++ is a big, historically grown language that emphasizes enabling the programmer to do what he wants over safety and ease-of-use, and not all of its features in all their flexibility are necessary to build good programs. There are many coding standards that restrict the use of some features; for example Google's guidelines mostly forbid multiple inheritance, complex templates, and exceptions (though that last one is for historical reasons). But no feature is forbidden "because Java doesn't have it"; the features are considered within the framework of C++ alone.

10
  • 27
    Seasoned C++ veterans usually reject Google coding guidelines. Modern C++ is vastly better exactly because it uses those features. Yes, it makes it even more different.
    – Jan Hudec
    Commented Jan 25, 2016 at 13:36
  • 17
    Note that C++ does not have finally blocks, but it has RAII, which is much better for most cases. And, again, different.
    – Jan Hudec
    Commented Jan 25, 2016 at 13:36
  • 7
    Java's Object is pretty much a void* for most uses -- Still, yuck.
    – Quentin
    Commented Jan 25, 2016 at 13:44
  • 1
    Beyond the choice of features, there is the matter of style and idiom. Programs are generally easier to read and maintain if they use the normal idioms for the language in which they were written. Even if one could write a portion of a C++ program using only Java-like features, the result would be strange, stilted C++. Commented Jan 25, 2016 at 14:48
  • 2
    I would upvote this answer for being in the right track ("don't do it"), but I cannot stand the basic premise that Java is somehow "more advanced" than C++. C++ does not need a garbage collector or a single-root object hierarchy, the same way Java does not need... err... sorry I don't know how to finish the sentence, because I miss deterministic destructors in Java, and finally isn't a replacement for them. The two languages are just fundamentally different.
    – DevSolar
    Commented Jan 27, 2016 at 15:20
25

I've debated whether to bother posting another answer when you already have a number that reach what seem to be entirely reasonable conclusions: that your idea is basically a disaster waiting to happen. I think, however, they've failed to point out some highly relevant reasons behind that conclusion.

The differences between Java and C++ run much deeper than the details upon which you seem to have focused.

For example, you talk about prohibiting multiple inheritance in C++. First, I'll point out that this is simply missing the point. Java defines "interfaces" as separate things from "classes". One class inherits from only one other class, but can implement an arbitrary number of interfaces.

C++ doesn't separate the two concepts that way. The closest analog C++ provides to implementing an interface in Java is inheriting from another class. As such, to keep the two aligned reasonably well at all, you probably need to use multiple inheritance in C++, but you want to restrict some of those base classes in roughly the same ways Java restricts an interface compared to a class (i.e., essentially that it specifies function signatures but, at least mostly, not implementations).

That's barely scratching the surface of the real differences between the two though. In reality, where Java code is likely to define interfaces, and classes that implement those interfaces, C++ code is a lot more likely to define some templates that will work with any class that meets its requirements (not just those defined specifically to implement the interface(s) it specifies).

If you honestly want code that's basically "Java using C++ syntax", you're almost certainly going to have to prohibit anything and everything similar to the latter though. You'll need to restrict your use of templates to roughly the level of "container of T" that Java generics support. Unfortunately, doing that will result in C++ code that's such a mess that nobody can maintain it as it exists now, not to mention the long-term possibility of translating it to some other programming language.

If you really want code that can be converted to some other language in the future, strive to make it as clean and readable as possible. The ideal is to write pseudo-code and still have it execute. Well-written modern C++ approaches that ideal much more closely than the subset you've suggested. No matter how you write it, if you ever translate to Java, you're going to have to actually translate the code, not just the syntax of the individual statements.

5
  • Many C++ features can be used in some ways which map nicely to Java concepts, and other ways which don't. Some parts of a program are going to require something outside the overlapping subset of the languages' functionality, and attempting to write such parts as "Java using C++ syntax" is going to yield a horrible mess. On the other hand, many other parts of the code may need anything outside the shared subset, and trying to stay within the shared for those portions of the code where there's no compelling reason to go outside it may be helpful.
    – supercat
    Commented Jan 28, 2016 at 18:19
  • Presumably where you say "may need", you really mean: "may not need"? Assuming so, then I'd tend to agree. Commented Jan 28, 2016 at 18:23
  • Yup. If it becomes necessary to support a platform which supports Java but not C++, parts of the code will almost certainly have to be rewritten from scratch and it won't matter whether those parts had been written using some Java-friendly techniques, since they'll be rewritten anyway. It may be possible to write other parts, however, in a way that would allow them to be migrated without a full rewrite, and in some cases the extra cost required to do so may be minimal.
    – supercat
    Commented Jan 28, 2016 at 18:38
  • 4
    @supercat: OTOH, given the number of platforms that support Java but not C++, this strikes me as almost entirely a solution in search of a problem. Commented Jan 28, 2016 at 18:47
  • For awhile, browser support for Java applets was better than for C++ applets. Browser support for JavsScript (no relation to Java), however, has improved enough that it's basically taken over from both.
    – supercat
    Commented Jan 28, 2016 at 19:11
11

If you're going to write code in language X, spend the time to properly learn the language and use all the features it offers to help you solve the problem. Bad things happen when you try to do a "word for word" translation from one language to another, whether that's Japanese to English or Java to C++. It's far better to start with a good understanding of the problem and express the solution in the way that is the most natural for the language being used.

Years ago I saw a C program that had no indentation and every statement started in column 7, because the author of the code was a Fortran programmer that happened to be using C. Other Fortran programmers were nervous about these newfangled things called pointers. I didn't have the heart to mention pointers to pointers, I think they would have fainted on the spot.

Imagine hiring somebody to maintain this code in the future. If it's good C++ code, you'll be able to hire a competent C++ developer and they should be able to find their way around. If it's "Java in C++", then neither C++ nor Java developers will have an easy time understanding the code.

7

All of your reasons can be disproved:

If Java doesn't provide a feature that C++ has, it means that the feature is not good, so we should prevent using it.

It doesn't mean the the feature is not good (no feature can be inherently bad). It only means that the feature was frequently misused (or impossible to implement due to fundamental concepts, like direct pointers vs garbage collection). Java by definition is aimed to be easier and more programmer-friendly, hence the removal of features that proven themselves to be easily abusable.

C++ code with C++ specific features (e.g.: friend functions, multiple inheritance) can only be maintained or reviewed by C++ programmers, but if we just write C++ like Java (without C++ language specific feature), the code can be maintained or reviewed by both C++ and Java programmers.

Oh can it be? Let's see simplest C++ code:

int len = mystring->size();

Oops, no "language-specific" features used, yet it's already unmaintainable by Java devs! Because in Java you dereference with "." while here it's "->.

You may be asked to convert the code to Java some day

Or C#. Or Haskell. Or Python. Or Ruby. Or COBOL (yes, you can!). How can you tell the future?

Code without C++ specific features is usually more maintainable.

Exactly opposite. Every feature was introduced in order to make programming easier hence more maintainable. Eg: take a program operating on floats. Now upgrade it to handle complex numbers. Operator overloading to the rescue!

Every C++ language specific feature (e.g.: multiple inheritance) should have alternatives to be implemented in Java. If it doesn't, that means the design pattern or code architecture is problematic.

But Java DOES have multiple inheritance! It's called "interface". Java implementation is a problematic workaround to avoid the dreaded diamond caused by having everything derive from Object. It's done by introducing interface which sole purpose is to be something that does not derive from Object. C++ never had this problem - there is no mandatory common base so every class can function as an interface without the dreaded diamond.

Side note: Java recently introduced ... concrete methods in interfaces. Added a feature C++ always had to solve a problem that was never there.

You've also only mentioned very few "things that C++ has but Java does not". One of the biggest differences between C++ and Java is the control over memory layout. You can create array of pointers to objects (just like in Java) OR you can create contiguous memory block. Now, if I was to worry about a C++ feature that may mislead Java devs, something as hidden and subtle as this one would rank on my list much higher than obvious and recognizable on first sight things like multiple inheritance or overloaded operators.

Bottom line: Clean code is clean code. Java or C++ - same difference. Just keep it simple. Unnecessary complications are the leading cause of bad code.

3
  • Java offers some features and guarantees which would be unsupportable in a language which offers all the features of C++. A language cannot, for example, allow dynamic type loading and Java's full range of identity-preserving casts while offering the generalized forms of multiple inheritance included in C++.
    – supercat
    Commented Jan 25, 2016 at 20:00
  • @supercat I don't understand why you're saying this here. The question is not about Java features that can't be reproduced in C++, it's about C++ features that Java discarded.
    – Agent_L
    Commented Jan 26, 2016 at 8:19
  • My point is that some features in Java aren't included in C++, but rather that some features of Java are fundamentally incompatible with other features that are included in C++, such that no language could have types that support both (languages like C++/CLI have types that support C++ features and types that support Java-ish features, but they effectively inhabit separate universes with limited interoperability).
    – supercat
    Commented Jan 26, 2016 at 16:45
6

No, you should generally not write C++ like it was Java, and you should definitely not omit C++ language features that aren't present in Java.

For one thing, Java is garbage collected, and thus has no equivalent of the C++ "delete" keyword. Okay, so you implement a program without delete, because per your rules, it's not allowed.

Congratulations, you now have a memory leak ;). That's not theoretical, either - I've seen this exact situation happen in an open source game.

Similarly, Java doesn't have anything quite like C++ pointers, which rules out a lot of common function call conventions.

There are features of C++ which you should maybe avoid (see below), but "not being in Java" is not a good litmus test.


Better guidelines would be the following:

  1. Write code that is appropriate for your language, environment, and tools.
  2. Write code that your team can understand.
  3. Make sure that your team is competent in the given domain.

Item (3) means that you should not have Java programmers code in C++ without training them in C++. There are some subtle but very important differences which they might not learn if they're trying to treat it like a weird dialect of Java.

Item (2) means that, if your team specifically is uncomfortable with multiple inheritance (for example), and if there's an adequate solution which doesn't use it, then it may be best to use that alternate solution. However, this depends on your team specifically. On the other hand, if your team is more uncomfortable with that alternate solution than with multiple inheritance, use multiple inheritance!


Lastly, there ARE language features of C++ that, arguably, one should avoid. If you want to know what these are, ask C++ programmers, rather than programmers of a different language. Some examples to start with are pointer arithmetic (no universal consensus) and goto.

6

There are already some good points in other answers, but I'd like to provide a more complete answer, addressing your questions and statements individually.


If Java doesn't provide a feature that C++ has, it means that the feature is not good, so we should prevent using it.

This has been pretty well answered: Java isn't "the good parts" of C++, nor is there any reason to think so.

In particular, though the merits of each individual C++ feature are debatable, many of the features of C++11/C++14 that are not part of Java aren't necessarily excluded because the Java designers thought they were a poor idea. As an example case, until version 8, Java didn't have lambdas, but they were introduced to C++ in the C++11 standard. Prior to Java 8, your assumption that C++ features missing from Java were missing by design because they are "not good" would have implied that lambdas as a language feature are "not good" (to the horror of LISPers everywhere, though they're probably horrified enough to hear that you apparently actually like Java). But now the Java designers have put their Stamp of Approval (TM) on lambdas, so they're now A Good Thing.

To dig a little deeper, even in Java 8, lambdas-as-closures are not as flexible as C++14's lambdas, but this may be due to JVM architecture limitations rather than a conscious decision that the more flexible approach is bad from a language-design perspective.


C++ code with C++ specific features (e.g.: friend functions, multiple inheritance) can only be maintained or reviewed by C++ programmers, but if we just write C++ like Java (without C++ language specific feature), the code can be maintained or reviewed by both C++ and Java programmers.

This is the main thing I wanted to respond to.

Broadly speaking, there may be some value to getting code reviews from programmers who aren't intimately familiar with the language you're using. They can give you valuable feedback about the clarity of your function/method names and comments, and (as your question correctly implies) if the language is similar to one or more languages they already know, they may be able to follow the basic program flow and potentially catch logic errors.

However, it is not the case that this sort of review will ever be "as good as" or "equivalent to" review from developers who actually know the language you're using. Essentially, this is because making one language look like another will typically hide subtle differences, while making one language behave like another (especially in the case of C++ and Java) may be un-idiomatic for the language and/or might still be too confusing for the reviewers.

First, let's think about what it would mean to make C++ "look like" Java. As a simple case, you can use new to instantiate objects, just like in Java:

Foo foo = new Foo();

But objects instantiated this way use -> instead of . to call methods, so if you want method calls to look like Java, you must instead write:

Foo& foo = *new Foo();

But this is un-idiomatic; in particular, the memory must later be cleaned up using delete &foo, which some experienced C++ devs might not even realize is legal code. Either way, there are funny non-Java-like symbols sprinkled throughout, so we can't quite make the language "look like" Java. (You could eliminated *new using #define New *new, or, worse, #define new *new, but then you're just begging for your fellow developers to hate you.) And, as mentioned above, delete doesn't exist in Java, so in any case (as mentioned in another answer) you can't really ever make object-usage "look" the way it does in Java without memory leaks.

But modern C++ includes smart shared pointers, which behave a lot like Java's memory-managed variable-references. So everywhere in Java that you could write Foo foo = new Foo();, you could instead write:

std::shared_ptr<Foo> foo = std::make_shared<Foo>();

Now you're using a language feature that's actually a lot like Java's under the hood. But suddenly you have a lot to explain to non-C++ reviewers: what is this shared_ptr stuff? What are the subtle tricky "gotchas" of make_shared? (It uses perfect-forwarding, which has some failure cases and can lead to the "wrong" constructor being called.) Why do methods need to be called with ->, but using . with some methods is permitted by the compiler? (shared_ptr has its own methods.) If the method Foo::reset(void) exists, an unwary developer might try to call it with foo.reset(), which (if there is only one shared pointer pointing to that instance of Foo when the call occurs) will delete the underlying memory and nullify foo, and Java developers aren't likely to catch this problem.

Moreover, C++ has a lot of pitfalls that are specific to the language. As best I can tell, most C++ developers learn to deal with these pitfalls by gradually developing their own idiom for "safe" C++ practices, which is often somewhat unique to them or to their development team (see for example the existing answer that mentions the Google coding practices and the comment on it saying that "Seasoned C++ veterans usually reject Google coding guidelines"). All claims that the language might be too complicated, it seems (in my experience, at least), are typically met with some variation of "well, stop using it wrong." I realize this is a highly negative view of the C++ community, and there are certainly experienced developers more willing to help out language-learners, but there does seem to be a certain defensiveness about e.g. undefined behavior (see for instance much of the discussion in my 'pitfalls' link above).

Java developers simply won't be helpful in finding and correcting these pitfalls via code review.


You may be asked to convert the code to Java some day.

It's entirely valid--commendable, even--to try to take into account what might happen to your code in the future while you're in the design phase.

But, first, this particular consideration seems like a remote possibility: code is typically either re-used as is (for instance you could plug some or all of the working C++ code into some future Java software using a JNI interface) or rewritten entirely rather than directly manually "transcribed".

And, second, you later say,

Every C++ language specific feature (e.g.: multiple inheritance) should have alternatives to be implemented in Java....

This essentially cancels out your "convert to Java" point. If software is written in idiomatic C++ and then converted to idiomatic Java, there's no reason to expect that this conversion would (or could!) be done by applying a precise one-to-one mapping of C++ features to Java features.


Code without C++ specific features is usually more maintainable.

It's not clear what you mean here, but I actually somewhat agree with part of this: unless you're very careful, and even when you are careful, C++ features can lead to maintainability problems. The C++ FQA Lite (a website critical of the language and its adherents from someone who at least appears to actually understand it fairly well) states that

... 80% of the developers understand at most 20% of the language. It is not the same 20% for different people, so don't count on them to understand each other's code.

PLEASE NOTE: If you're a C++ fan and you get to this point in my answer and feel inclined to jump down to the comments to argue that the author of the FQA doesn't actually understand C++ or is disingenuous in most of his arguments, note that (1) exactly two sentences after I cite him I acknowledge that the FQA is a very biased source, and (2) it doesn't really matter for what I'm trying to say whether or not the FQA author understands C++, and I'm not trying to bash C++, and you should read the rest of the post without assuming that I'm anti-C++ just because I've quoted the FQA. End of note.

Similarly, Linus Torvalds hates C++ for essentially this reason (warning: link involves lots of swearing, in true infamous Linus style).

Obviously, these are very biased takes on the matter, but even C++ proponents often say that you shouldn't use the entirety of the language feature-set (once again, see the Google coding guidelines; also, Bjarne Stroustrup, the creator of C++, has publicly stated, "Within C++, there is a much smaller and cleaner language struggling to get out").

So I think there's some merit to the idea that C++ features might be too easy to misuse, especially if you're coming from a Java background. Furthermore, there's merit to the idea of alleviating these problems by restricting yourself to some subset of the language.

However, deciding which subset to use based on a different language does not seem like the right approach, unless the "different language" is C, since there really is a C-like subset of the C++ language. (Linus refers to this in his rant above, and Scott Meyers even refers to this subset as a "sub-language.") Java's run-time paradigm (garbage-collected, running on a VM) is so fundamentally different from C++'s that it's not clear there are any useful lessons to draw about C++ usage from it, and as noted above, trying to draw lessons about C++ directly from Java can lead to very non-idiomatic code.

Instead, try to define your "acceptable subset" of the language on an understanding of how the language can be used idiomatically. If you want a fairly restrictive subset that still takes advantage of many of C++'s features beyond what C offers, the aforementioned Google Coding guideline might be a good place to start. Sure, you'll get developers who say that there is "no rational argument" for some of Google's restrictions, but unless you're looking to hire Alexandrescu away from his work on the D language (which itself should tell you something), that's probably okay. It's certainly better than trying to turn C++ into Java.

Another good starting-point for a set of code guidelines is the new C++ Core Guidelines, a work-in-progress by Bjarne Stroustrup and Herb Sutter.

The only other way to deal with the shortcomings of C++ is to pick a different language. It sounds like you like Java, and you think there's a chance this project might be converted into Java eventually. As noted in another answer, you could just...start with Java.

There are two reasons why you might really truly need to use something other than Java:

  1. You really need the run-time performance. In this case, treating C++ like it's Java probably won't actually help you, because Java-like techniques such as shared-pointers degrade your run-time performance.
  2. You need the software to work on an obscure platform that doesn't yet support the JVM. In this case, you are probably stuck with languages that have GCC or Clang frontends. C and C++ are obvious candidates, but you could also look into something like Rust. (Quick plug: I haven't used Rust extensively, but it looks awesome and I am eager to work on a major Rust project as soon as I can, and I think everyone considering starting a C++ project should consider Rust as an alternative.)

Every C++ language specific feature (e.g.: multiple inheritance) should have alternatives to be implemented in Java. If it doesn't, that means the design pattern or code architecture is problematic.

I've already addressed this somewhat, but I intentionally left out your second sentence.

I'm not convinced that something like constexpr, which wouldn't make any sense in a partially-JIT language like Java, is an indication of invalid architecture. I'm more open to the idea that excessive use of template meta-programming might be more trouble than it's worth, especially now that constexpr exists for doing compile-time function evaluation, but it's clear from the case of constexpr that there's no design flaw if you're using it: you're simply ensuring that some calculations occur prior to even running the code, which is an awesome performance boost (see for instance this entry for The Benchmark Game's n-body problem, which outperforms every other entry except another one written in C++, and is over twice as fast as the fastest Java implementation).

12
  • 5
    The FQA author definitely falls into the "understand at most 20% of the language" group. Quite a few answers there that are factually wrong, and a whole bunch more that just miss the point, illustrated with strawman after strawman.
    – Ben Voigt
    Commented Jan 27, 2016 at 20:44
  • 2
    Many (almost all?) of the complaints in the C++ FQA are nonsense. Modern languages are huge. C++ is rather small in comparison to Python, Ruby, Perl, and yes, Java. Ask a basic question in those languages on stackoverflow and the first answer is almost inevitably along the lines of "Why didn't you import SomeVeryBasicPackage and just do this?" Ask an advanced question and the first answer is almost inevitably along the lines of "Why didn't you import SomeMagicalPackage and just do that?" Commented Jan 30, 2016 at 19:52
  • 1
    @DavidHammen I think the 80/20 split refers to core language features, not just standard library components, in which case the languages you mention, with the possible exception of Perl, really don't seem to be as big and complicated as C++. In any case, that was a very small part of my answer, and I acknowledged that it's a biased source. Commented Jan 30, 2016 at 21:16
  • 1
    VM/managed languages are obviously much more complicated under the surface, but I mean complicated from a use perspective. Commented Jan 30, 2016 at 21:18
  • 1
    I have no idea if your theory is correct, though in my case I definitely learned C++ and C separately, and my C++ class was really quite thorough. But the full quote about the 20/80 split is that every programmer knows a different 20% of the language, which wouldn't be explained by most programmers being taught the C part of the language independently. Anyway, if you'd like to explain in detail how C++ permits more robust programming (I claim I've seen before but do not understand), we'd probably best do it in a chat room or something rather than in the comments here. Commented Oct 2, 2016 at 21:11
5

Suppose I am limited to use C++ by the environment in the project. Is it good to prevent the use of some language features that C++ has but Java doesn't have (e.g.: multiple inheritance, operator overriding)?

No.

If "by the environment of the project" you are limited to using C++, then there is little, if any, point in even thinking about any other technology, no matter how much you might personally prefer/hope to use/evangelise it.
Whether "Technology X" or "Y" supports any given feature should have no bearing whatever on the way in which you build your C++ application.
It's a C++ application, presumably for some "Good Reason" (now or in the past) so you should write it as a C++ application, using whatever that particular "toolbox" provides.

If and when there's a Requirement to port the application to some other technology then (and only then) you might consider features on other platforms. There is no point "cutting off your nose to spite your face" on the off-chance that something might happen. Remember, though, that wholesale re-writing is an expensive, risky operation that Management are unlikely to take on without a very Good Reason to do so.

There was a similar ("to use or not to use") debate some years back in the Visual Basic [.Net] World, where Someone had the bright idea that you should write Visual Basic applications without using any of the [core language] functionality provided by the Microsoft.VisualBasic namespace. It'd be like trying to write a C++ application without the std:: namespace; OK, it's possible but why on Earth would anyone in their right mind bother to do so?

2
  • 1
    To your last point about Visual Basic: The problem with such vendor libraries is that they are proprietary. Using them means chaining yourself to that vendor. The vendor will like you being chained, but you won't in the long run: You can't use the software of another vendor without rewriting everything that relies on vendor specific functionality. The more you use vendor specific functionality, the higher the cost of changing vendors becomes, empowering your vendor to force changes on you. That's one of the reasons why free (as in freedom!) software is such a big deal. Commented Jan 25, 2016 at 21:08
  • The Microsoft.VisualBasic namespace thing is a bit of a stretch. It's many years since I last used it, but at least at the beginning it was mostly aimed to backwards compatibility with VB6 (and/or to make VB6 programmers feel "at home"); it mostly provided functionality that was already available in the rest of the framework in a more modern (and better integrated) form, so in new projects it rarely made sense to use it. To the opposite, the std:: namespace is where the whole standard library reside - avoiding it would be like avoiding the whole BCL in .NET. Commented Jan 28, 2016 at 14:58
2

The current answers all say this is a bad thing to do, as you should take advantage of the language you are using and also explain why a C++ feature is not “bad” just because it is not in jave. I will answer this from a different angle.

It is one thing to avoid complex C++ feature like multiple inheritance, operator overloading and defining your own template.

But any problem that does more than the most simple task:

  • allocates memory,
  • connects that money together with points
  • so build data structures
  • then allows the memory to be reused when safe to do so

There is not a common subset of Java and C++ that allows the above, therefore what you are asking is impossible to do. (If you were asking about Java and C# you would have a lot better chance, as they both use garbage collectors.)

However you could require that the code be written so that a Java developer could understand what is does (but not the detailed "how") and this would be sensible.

You could also design your own language that you implemented in both C++ and JAVA.....

0

No one should be writing any code that other coders don't understand. If you think language lock is a problem, wait until you have developer lock. One is more likely to hold you hostage than the other.

There really are no technical reasons. What you've created is a scenario where a language was used for whatever reason, but many current and possibly future developers don't really understand it.

My guess is, Java developers are likely to write C++ the way they write in Java, so why make it a rule. You may discover some C++ specific features that are easier to implement and maintain with a little C++ instruction/documentation for your Java developers than the big ball of Java mess they would otherwise be stuck with.

This has been an argument about the problems of BASIC programmers moving to object-oriented languages. It's not that they implement OOP practices at the detriment of new devs who don't understand it, but that they don't implement it at all. If they do, they usually get it wrong. If something is done poorly, it needs to be removed regardless of the reason.

Other than someone just blindly copying and pasting code, they're going to do it in many areas they don't understand anyway.

Not the answer you're looking for? Browse other questions tagged or ask your own question.