C++ Programming - Chapter 1



Authors

The following people are authors to this book:

Panic, Thenub314

You can verify who has contributed to this book by examining the history logs at Wikibooks (http://en.wikibooks.org/).

Acknowledgment is given for using some contents from other works like Wikipedia, the wikibooks Java Programming and C Programming and the C++ Reference, as from the authors Scott Wheeler, Stephen Ferg and Ivor Horton.

The above authors release their work under the following license:
Unless otherwise noted media and source code and source code usable in stand alone form have their own copyrights and different licenses (but compatible with the Copyleft nature of the work). Media may be under Fair use, that is not recognized in some jurisdictions. Source code or scripts not listing copyrights or license information shall be considered in the public domain.

C++ a multi-paradigm language

Introducing C++

 

C++ (pronounced "see plus plus") is a general-purpose, multi-paradigm, statically typed, free-form programming language, supporting procedural; object-oriented; generic; and (more recently) functional programming paradigms, and is well-known for facilitating low-cost abstractions in code. If any of the preceding concepts are unfamiliar to you, do not worry, they will be introduced in subsequent sections.

During the 1990s C++ grew to become one of the most popular computer programming languages, and it is still the fourth most popular language, according to the TIOBE index.[1] C++ was first designed with a focus on systems programming, but its features also make it an attractive language for creating end-user applications, especially those with resource constraints, or that require very high performance. C++ is extensively used in game development, web clients/server side, back office of financial applications and robotics.

History and standardization

 
Photo of Bjarne Stroustrup, creator of the programming language C++.

Bjarne Stroustrup, a Computer Scientist from Bell Labs, was the designer and original implementer of C++ (originally named "C with Classes") during the 1980s, as an enhancement to the C programming language. C, which had also been created at Bell Labs for the purpose of implementing the Unix operating system by Dennis Ritchie, gave users great control over hardware at a higher conceptual level than assembly language (ASM), but still with limited expressivity. Stroustrup decided to combine features for program organization from the object-oriented Simula language with C's efficient use of hardware resources. Enhancements started with the addition of object-oriented concepts like classes and virtual functions, followed by, among many features, namespaces, operator overloading, templates, and exception handling. These and other features are covered in detail in this book. Several features of C++ were later adopted by C, including the const keyword for creating immutable values in a program, inline functions, declarations in for loops , and C++-style comments (using the // symbol).

The C++ programming language is a standard recognized by the ANSI (The American National Standards Institute), BSI (The British Standards Institute), DIN (The German national standards organization), and several other national standards bodies, and was ratified in 1998 by the ISO (The International Standards Organization) as ISO/IEC 14882:1998, though more commonly referred to as C++98 or simply C++. The standard consists of two parts: the Core Language and the Standard Library; the latter includes the Standard Template Library and the Standard C Library (ANSI C 89).

The 2003 version, ISO/IEC 14882:2003, referred to as C++03, redefined the standard language as a single item. The STL ("Standard Template Library") that pre-dated the standardization of C++ (and was originally implemented in Ada) became an integral part of the standard, and a requirement for a compliant implementation of the same.

From 2004, the standards committee (which includes Bjarne Stroustrup) worked out the details of a new revision of the standard, with C++11 (previously called C++0x) approved on 12 August 2011. C++11 made the language more efficient, easier to use, and added more functionality to the Standard Library. The specification for C++14 was released on 15 December 2014, with smaller changes compared to C++11, and compiler support for this standard has followed quickly. Several tables of compiler support for so-called modern C++ features are available.


 

To do:
Add entries for C++17 and C++20.


Many other C++ libraries exist which are not part of the Standard, a popular example being Boost. Also, non-Standard libraries written in C can generally be used by C++ programs.

C++ source code example
// 'Hello World!' program 
 
#include <iostream>
 
int main()
{
  std::cout << "Hello World!" << std::endl;
  return 0;
}


Traditionally, the first program people write in a new language is called "Hello World", because all it does is simply display the words Hello World, while revealing basic information about the language in the process. Hello World Explained (in the Examples Appendix) offers a detailed explanation of this code, in which can be seen several elements of C++ mentioned here, including C-like syntax and use of the Standard Library.

Overview

Before you begin your journey to understand how to write programs using C++, it is important to understand a few key concepts that you may encounter. These concepts are not unique to C++, but are helpful to understanding computer programming in general. Readers who have experience in another programming language may wish to skim through this section, or skip it entirely.

There are many different kinds of programs in use today. From the operating system you use that makes sure everything works as it should, to the video games and music applications you use for entertainment, programs can fulfill many different purposes. What all programs (also called software or applications) have in common, is that they all are made up of a sequence of instructions written, in some form or another, in a programming language. These instructions tell a computer what to do, and generally how to do it. Programs can contain anything from instructions to solve math problems, to how to behave when a video game character is shot in a game. The computer will follow the instructions of a program one instruction at a time from start to finish.

Another thing true of all computer programs (or most programs, rather) is that they solve problems and perform tasks. Say hello to the world. Paint a button on the screen. Calculate 26*78. Drive the car. Fortunately or not, computers must be taught how to perform these tasks. In other words, they must be programmed.

Why learn C++?

Why not? This is the most clarifying approach to the decision to learn anything. Although learning is always good, selecting what you learn is more important as it is how you will prioritize tasks. Another side of this problem is that you will be investing some time in getting a new skill set. You must decide how this will benefit you. Check your objectives and compare similar projects or see what the programming market is in need of. In any case, the more programming languages you know, the better.

C++ is not the ideal first language. However, if you are willing to dedicate a more than passing interest in C++, then you can even learn it as your first language. Make sure to dedicate some time understanding the different paradigms and why C++ is a multi-paradigm, or hybrid, language.

If you are approaching the learning process only to add another notch under your belt, that is, willing only to dedicate enough effort to understand its major quirks and learn something about its dark corners, then you would be best served in learning two other languages first. This will clarify what makes C++ special in its approach to programming. You should select one imperative and one object-oriented language. C will probably be the best choice for the former, as it has a good market value and a direct relation to C++, although a good substitute would be ASM. For the latter, Java is a good choice, mostly because it shares much of its syntax with C++ but it does not support imperative programming. Read the language comparison section for better understanding the relations.

Although learning C is not a requirement for understanding C++, you must know how to use an imperative language. C++ will not make it easy for you to understand some of these deeper concepts, since in it you, the programmer, are given the greater range of freedom. There are many ways of doing things in C++. Understanding which options to choose will become the cornerstone of mastering the language.

You should not learn C++ if you are solely interested in learning Object-oriented Programming. C++ offers some support for objects, but is still not truly Object-oriented, and consequently the nomenclature used and the approaches taken to solve problems will make it more difficult to learn and master those concepts. If you are truly interested in Object-oriented programming, you should learn Smalltalk.

As with all languages, C++ has a specific scope of application where it can truly shine. C++ is harder to learn than C and Java but more powerful than both. C++ enables you to abstract from the little things you have to deal with in C or other lower level languages but will grant you more control and responsibility than Java. As it will not provide the default features you can obtain in similar higher level languages, you will have to search and examine several external implementations of those features and freely select those that best serve your purposes (or implement your own solution).


What is a programming language?

In the most basic terms, a "programming language" is a means of communication between a human being (programmer) and a computer. A programmer uses this means of communication in order to give the computer instructions. These instructions are called "programs".

Like the many natural languages we use to communicate with each other, there are many languages that a programmer can use to communicate with a computer. Each programming language has its own set of words and rules, called the syntax of that language. If you're going to write a program, you have to follow the syntax of the language you're using, otherwise you won't be understood.

Programming languages can generally be divided in two categories: Low-Level and High-level, both concepts will be introduced to you and their relevance to C++.

Low-level

 
Image shows most programming languages and their relations from the mid-1800s up to 2003 (click here for full size).

The lower level in computer "languages" are:

Machine code (also called binary) is the lowest form of a low-level language. Machine code consists of a string of 0s and 1s, which combine to form meaningful instructions that computers can take action on. If you look at a page of binary it becomes apparent why binary is never a practical choice for writing programs; what kind of person would actually be able to remember what a bunch of strings of 1 and 0 mean?

Assembly language (also called ASM), is just above machine code on the scale from low level to high level. It is a human-readable translation of the machine language instructions the computer executes. For example, instead of referring to processor instructions by their binary representation (0s and 1s), the programmer refers to those instructions using a more memorable (mnemonic) form. These mnemonics are usually short collections of letters that symbolize the action of the respective instruction, such as "ADD" for addition, and "MOV" for moving values from one place to another.

Note:
Assembly language is processor specific. This means that a program written in assembly language will not work on computers with different processor architectures.
Using ASM to optimize certain tasks is common for C++ programmers, but will require special considerations, because ASM is not as portable.

You do not have to understand assembly language to program in C++, but it does help to have an idea of what's going on "behind-the-scenes". Learning about assembly language will also allow you to have more control as a programmer and help you in debugging and understanding code.

The advantages of writing in a high-level language format far outweigh any drawbacks, due to the size and complexity of most programming tasks, those advantages include:

  • Advanced program structure: loops, functions, and objects all have limited usability in low-level languages, as their existence is already considered a "high" level feature; that is, each structure element must be further translated into low-level language.
  • Portability: high-level programs can run on different kinds of computers with few or no modifications. Low-level programs often use specialized functions available on only certain processors, and have to be rewritten to run on another computer.
  • Ease of use: many tasks that would take many lines of code in assembly can be simplified to several function calls from libraries in high-level programming languages. For example, Java, a high-level programming language, is capable of painting a functional window with about five lines of code, while the equivalent assembly language would take at least four times that amount.

High-level

High-level languages do more with less code, although there is sometimes a loss in performance and less freedom for the programmer. They also attempt to use English language words in a form which can be read and generally interpreted by the average person with little to no programming experience. A program written in one of these languages is sometimes referred to as "human-readable code". In general, abstraction makes learning a programming language easier.

No programming language is written in what one might call a natural language like "plain English" though, (although BASIC and COBOL come close and someone is working hard at it in the Osmosian Order's Plain English compiler and Integrated Development Environment, which is written entirely in Plain English, being plain English then open to debate regarding its definition). Anyhow, because of this necessity for reduction and control regarding written expression that results in the use of programming languages (constructed and formal languages) the text for the program is sometimes referred to as "code" or more specifically as "source code." This is discussed in more detail in The Code Section of the book.

The important bits to retain is that while some words (instructions) are in English (mostly for ease) the language used is different (with generally good reasons why, otherwise someone will create a new programming language), beyond that the rest of above paragraph may only be of importance when you start building parsers, languages and compilers. The Higher-level a language is, the harder it works to solve the problem of abstraction to the hardware (CPU, co-processors, number of registers etc...) by supporting portability on code and higher human intelligibility via added complexity in expression and constructs.

Keep in mind that this classification scheme is evolving. C++ is still considered a high-level language, but with the appearance of newer languages (Java, C#, Ruby etc...), C++ is beginning to be grouped with lower level languages like C.

Translating programming languages

Since a computer is only capable of understanding machine code, human-readable code must be either interpreted or translated into machine code.

An Interpreter is a program (often written in a lower level language) that interprets the instructions of a program one instruction at a time into commands that are to be carried out by the interpreter as it happens. Typically each instruction consists of one line of text or provides some other clear means of telling each instruction apart and the program must be reinterpreted again each time the program is run.

A Compiler is a program used to translate the source code, one instruction at a time, into machine code. The translation into machine code may involve splitting one instruction understood by the compiler into multiple machine instructions. The instructions are only translated once and after that the machine can understand and follow the instructions directly whenever it is instructed to do so. A complete examination of the C++ compiler is given in the Compiler Section of the book.

The tools with which to instruct a computer may differ, however no matter which statements are used, just about every programming language will support constructs that accomplish the following:

Input
Input is the act of getting information from a device such as a keyboard or mouse, or sometimes another program.
Output
Output is the opposite of input; it gives information to the computer monitor or another display device or program.
Math/Algorithm
All computer processors (the brain of the computer), have the ability to perform basic mathematical computation, and every programming language has some way of telling it to do so.
Testing
Testing involves telling the computer to check for a certain condition and to do something when that condition is true or false. Conditionals are one of the most important concepts in programming, and all languages have some method of testing conditions.
Repetition
Perform some action repeatedly, usually with some variation.

Further examination and analysis of C++ language constructs is provided on the Statements Section of the book.

Believe it or not, that's pretty much all there is to it. Every program you have ever used, no matter how simple or complex, is made up of functions that function more or less like these. Therefore, one way to describe computer programming is the process of breaking a large, complex task up into smaller and smaller sub-tasks until eventually each sub-task is simplified enough to be performed with one of these functions.

C++ is mostly compiled rather than interpreted (there are some C++ interpreters), and then "executed" later. As complicated as this may seem, further on you will see how easy it can be.

So as we have seen in the Introducing C++ Section, C++ evolved from C by adding some levels of abstraction (so we can correctly state that C++ is of a higher level than C). We will learn the particulars of those differences in the Programming Paradigms Section of the book and for some of you that already know some other languages should look into Programming Languages Comparisons Section.


Programming paradigms

A programming paradigm is a model of programming based on distinct concepts that shapes the way programmers design, organize and write programs. A multi-paradigm programming language allows programmers to choose a specific single approach or mix parts of different programming paradigms. C++ as a multi-paradigm programming language supports single or mixed approaches using Procedural or Object-oriented programming and mixing in utilization of Generic and even Functional programming concepts.

Procedural programming

Procedural programming can be defined as a subtype of imperative programming as a programming paradigm based upon the concept of procedure calls, in which statements are structured into procedures (also known as subroutines or functions). Procedure calls are modular and are bound by scope. A procedural program is composed of one or more modules. Each module is composed of one or more subprograms. Modules may consist of procedures, functions, subroutines or methods, depending on the programming language. Procedural programs may possibly have multiple levels or scopes, with subprograms defined inside other subprograms. Each scope can contain names which cannot be seen in outer scopes.

Procedural programming offers many benefits over simple sequential programming since procedural code:

  • is easier to read and more maintainable
  • is more flexible
  • facilitates the practice of good program design
  • allows modules to be used again in the form of code libraries.

Note:
Nowadays it is very rare to see C++ strictly using the Procedural Programming paradigm, mostly it is used only on small demonstration or test programs.

Statically typed

Typing refers to how a computer language handles its variables, how they are differentiated by type. Variables are values that the program uses during execution. These values can change; they are variable, hence their name. Static typing usually results in compiled code that executes more quickly. When the compiler knows the exact types that are in use, it can produce machine code that does the right thing easier. In C++, variables need to be defined before they are used so that compilers know what type they are, and hence is statically typed. Languages that are not statically typed are called dynamically typed.

Static typing usually finds type errors more reliably at compile time, increasing the reliability of compiled programs. Simply put, it means that "A round peg won't fit in a square hole", so the compiler will report it when a type leads to ambiguity or incompatible usage. However, programmers disagree over how common type errors are and what proportion of bugs that are written would be caught by static typing. Static typing advocates believe programs are more reliable when they have been type checked, while dynamic typing advocates point to dynamic code that has proved reliable and to small bug databases. The value of static typing, then, presumably increases as the strength of the type system is increased.

A statically typed system constrains the use of powerful language constructs more than it constrains less powerful ones. This makes powerful constructs harder to use, and thus places the burden of choosing the "right tool for the problem" on the shoulders of the programmer, who might otherwise be inclined to use the most powerful tool available. Choosing overly powerful tools may cause additional performance, reliability or correctness problems, because there are theoretical limits on the properties that can be expected from powerful language constructs. For example, indiscriminate use of recursion or global variables may cause well-documented adverse effects.

Static typing allows construction of libraries which are less likely to be accidentally misused by their users. This can be used as an additional mechanism for communicating the intentions of the library developer.

Type checking

Type checking is the process of verifying and enforcing the constraints of types, which can occur at either compile-time or run-time. Compile time checking, also called static type checking, is carried out by the compiler when a program is compiled. Run time checking, also called dynamic type checking, is carried out by the program as it is running. A programming language is said to be strongly typed if the type system ensures that conversions between types must be either valid or result in an error. A weakly typed language on the other hand makes no such guarantees and generally allows automatic conversions between types which may have no useful purpose. C++ falls somewhere in the middle, allowing a mix of automatic type conversion and programmer defined conversions, allowing for almost complete flexibility in interpreting one type as being of another type. Converting variables or expression of one type into another type is called type casting.

Object-oriented programming

Object-oriented programming can be seen as an extension of procedural programming in which programs are made up of collections of individual units called objects that have a distinct purpose and function with limited or no dependencies on implementation. For example, a car is like an object; it gets you from point A to point B with no need to know what type of engine the car uses or how the engine works. Object-oriented languages usually provide a means of documenting what an object can and cannot do, like instructions for driving a car.

Objects and Classes

An object is composed of members and methods. The members (also called data members, characteristics, attributes, or properties) describe the object. The methods generally describe the actions associated with a particular object. Think of an object as a noun, its members as adjectives describing that noun, and its methods as the verbs that can be performed by or on that noun.

For example, a sports car is an object. Some of its members might be its height, weight, acceleration, and speed. An object's members just hold data about that object. Some of the methods of the sports car could be "drive", "park", "race", etc. The methods really do not mean much unless associated with the sports car, and the same goes for the members.

The "blueprint" that lets us build our sports car object is called a class. A class does not tell us how fast our sports car goes, or what color it is, but it does tell us that our sports car will have a member representing speed and color, and that they will be say, a number and a word, respectively. The class also lays out the methods for us, telling the car how to park and drive, but these methods can not take any action with just the blueprint - they need an object to have an effect.

Class in C++ is the same as structure in C; The difference is that class users can hide data through the private option. In C++, an object is an instance of a class which is treated like a built-in variable which holds many values.

Encapsulation

Encapsulation, the principle of information hiding (from the user), is the process of hiding the data structures of the class and allowing changes in the data through a public interface where the incoming values are checked for validity, and so not only it permits the hiding of data in an object but also of behavior. This prevents clients of an interface from depending on those parts of the implementation that are likely to change in future, thereby allowing those changes to be made more easily, that is, without changes to clients. In modern programming languages, the principle of information hiding manifests itself in a number of ways, including encapsulation and polymorphism.

Inheritance

Inheritance describes a relationship between two (or more) types, or classes, of objects in which one is said to be a "subtype" or "child" of the other; as a result, the "child" object is said to inherit features of the parent, allowing for shared functionality. This lets programmers re-use or reduce code and simplifies the development and maintenance of software.

Inheritance is also commonly held to include subtyping, whereby one type of object is defined to be a more specialized version of another type (see Liskov substitution principle), though non sub-typing inheritance is also possible.

Inheritance is typically expressed by describing classes of objects arranged in an inheritance hierarchy (also referred to as inheritance chain), a tree-like structure created by their inheritance relationships.

For example, one might create a variable class "Mammal" with features such as eating, reproducing, etc.; then define a subtype "Cat" that inherits those features without having to explicitly program them, while adding new features like "chasing mice". This allows commonalities among different kinds of objects to be expressed once and reused multiple times.

In C++ we can then have classes that are related to other classes (a class can be defined by means of an older, pre-existing, class ). This leads to a situation in which a new class has all the functionality of the older class, and additionally introduces its own specific functionality. Instead of composition, where a given class contains another class, we mean here derivation, where a given class is another class.

This OOP property will be explained further when we talk about Classes (and Structures) inheritance in the Classes Inheritance Section of the book.

If one wants to use more than one totally orthogonal hierarchy simultaneously, such as allowing "Cat" to inherit from "Cartoon character" and "Pet" as well as "Mammal" we are using multiple inheritance.

Multiple inheritance

Multiple inheritance is the process by which one class can inherit the properties of two or more classes (variously known as its base classes, parent classes, ancestor classes, or super-classes).

Note:
In some similar languages, multiple inheritance is restricted in various ways to keep the language simple, such as by allowing inheritance from only one real class and a number of "interfaces", or by completely disallowing multiple inheritance. C++ places the full power of multiple inheritance in the hands of programmers, but it is needed only rarely, and (as with most techniques) can complicate code if used inappropriately. Because of C++'s approach to multiple inheritance, C++ has no need of separate language facilities for special language constructs that are usually called "interfaces", "traits" or "mixins" in other Object-Oriented languages, because C++'s classes themselves already provide this functionality.

This is shown in more detail in the C++ Classes Inheritance Section of the book.

Polymorphism

Polymorphism allows a single name to be reused for several related but different purposes. The purpose of polymorphism is to allow one name to be used for a general class. Depending on the type of data, a specific instance of the general case is executed.

The concept of polymorphism is wider. Polymorphism exists every time we use two functions that have the same name, but differ in the implementation. They may also differ in their interface, e.g., by taking different arguments. In that case the choice of which function to make is via overload resolution, and is performed at compile time, so we refer to this as static polymorphism.

Dynamic polymorphism will be covered deeply in the Classes Section where we will address its use on redefining the method in the derived class.


Generic programming

Generic programming or polymorphism is a programming style that emphasizes techniques that allow one value to take on different types as long as certain contracts such as subtypes and signature are kept. In simpler terms generic programming is based in finding the most abstract representations of efficient algorithms. Templates popularized the notion of generics. Templates allow code to be written without consideration of the type with which it will eventually be used. Templates are defined in the Standard Template Library (STL), where generic programming was introduced into C++.

Free-form

Free-form refers to how the programmer crafts the code. Basically, there are no rules on how you choose to write your program, save for the semantic rules of C++. Any C++ program should compile as long as it is legal C++.

The free-form nature of C++ is used (or abused, depending on your point of view) by some programmers in crafting obfuscated C++ (code that is purposefully written to be difficult to understand). In the right context this can also be seen as a show of craftsmanship (non functional but artful control over the language) but in general the use for obfuscation is seen only useful as a source security mechanism, ensuring that the source code is more intentionally difficult to analyze, replicate or use by third parties. With enough understanding about the compilers, source code can also be designed to preserve "water marks" in its compiled form that will permit tracing it to the original source.

Language comparisons

There is not a perfect language. It all depends on the resources (tools, people, and even available time) and the objective. For a broader look on other languages and their evolution, a subject that falls outside of the scope of this book, there are many other works available, including the Computer Programming wikibook.

This section is provided as a quick jump-start for people that already had some experience in them, a way to edify notions about C++ language's special characteristics, and as a demonstration of what makes it distinct.

Ideal language

The ideal language depends on the specific problem. All programming languages are designed to be general mechanisms for expressing problem-solving algorithms. In other words, it is a language - rather than simply an expression - because it is capable of expressing solutions to more than one specific problem.

The level of generality in a programming language varies. There are domain-specific languages (DSLs) such as regular expression syntax which is designed specifically for pattern matching and string manipulation problems. There are also general-purpose programming languages such as C++.

Ultimately, there is no perfect language. There are some languages that are more suited to specific classes of problems than others. Each language makes trade-offs, favoring efficiency in one area for inefficiencies in other areas. Furthermore, efficiency may not only mean runtime performance but also includes factors such as development time, code maintainability, and other considerations that affect software development. The best language is dependent on the specific objectives of the programmers.

Furthermore, another very practical consideration when selecting a language is the number and quality of tools available to the programmer for that language. No matter how good a language is in theory, if there is no set of reliable tools on the desired platform, that language is not the best choice.

The optimal language (in terms of run-time performance) is machine code but machine code (binary) is the least efficient programming language in terms of coder time. The complexity of writing large systems is enormous with high-level languages, and beyond human capabilities with machine code. In the next sections C++ will be compared with other closely related languages like C, Java, C#, C++/CLI and D.

The quote above is shown to indicate that no programming language at present can translate directly concepts or ideas into useful code, there are solutions that will help. We will cover the use of Computer-aided software engineering (CASE) tools that will address part of this problem but its use does require planning and some degree of complexity.

The intention of these sections is not to promote one language above another; each has its applicability. Some are better in specific tasks, some are simpler to learn, others only provide a better level of control to the programmer. This all may depend also on the level of control the programmer has of a given language.

Garbage collection

In C++ garbage collection is optional rather than required. In the Garbage Collection Section of this book we will cover this issue deeply.

Why no finally keyword?

As we will see in the Resource Acquisition Is Initialization (RAII) Section of the book, RAII can be used to provide a better solution for most issues. When finally is used to clean up, it has to be written by the clients of a class each time that class is used (for example, clients of a fileClass class have to do I/O in a try/catch/finally block so that they can guarantee that the fileClass is closed). With RAII, the destructor of the fileClass can make that guarantee. Now the cleanup code has to be coded only once — in the destructor of fileClass; the users of the class don't need to do anything.


 

To do:
Split this explanation to RAII and only provide the reference


Mixing languages

 

To do:
Add relevant information


By default, the C++ compiler normally "mangles" the names of functions in order to facilitate function overloading and generic functions. In some cases, you need to gain access to a function that wasn't created in a C++ compiler. For this to occur, you need to use the extern keyword to declare that function as external:

extern "C" void LibraryFunction();

C 89/99

C was essentially the core language of C++ when Bjarne Stroustrup decided to create a "better C". Many of the syntax conventions and rules still hold true, so we can even state that C was a subset of C++. Most recent C++ compilers can also compile C code, taking into consideration the small incompatibilities, since C99 and C++ 2003 are not compatible any more. You can also check more information about the C language on the C Programming Wikibook.

Note:
In practice, much C99 code will still compile with a C++ compiler, but the language is no longer a proper subset. Compatibility is not guaranteed.

C++ as defined by the ANSI standard in 1998 (called C++98 at times) is very nearly, but not quite, a superset of the C language as it was defined by its first ANSI standard in 1989 (known as C89). There are a number of ways in which C++ is not a strict superset, in the sense that not all valid C89 programs are valid C++ programs, but the process of converting C code to valid C++ code is fairly trivial (avoiding reserved words, getting around the stricter C++ type checking with casts, declaring every called function, and so on).

In 1999, C was revised and many new features were added to it. As of 2004, most of these new "C99" features are not in C++. Some (including Stroustrup himself) have argued that the changes brought about in C99 have a philosophy distinct from what C++98 adds to C89, and hence these C99 changes are directed towards increasing incompatibility between C and C++.

The merging of the languages seems a dead issue, as coordinated actions by the C and C++ standards committees leading to a practical result did not happen and it can be said that the languages started to diverge.

Some of the differences are:

  • C++ supports function overloading, this is absent in C, especially in C89 (it can be argued, depending on how loosely function overloading is defined, that it is possible to some degree to emulate these capabilities using the C99 standard).
  • C++ supports inheritance and polymorphism.
  • C++ adds keyword class, but keeps struct from C, with compatible semantics.
  • C++ supports access control for class members.
  • C++ supports generic programming through the use of templates.
  • C++ extends the C89 standard library with its own standard library.
  • C++ and C99 offer different complex number facilities.
  • C++ has bool and wchar_t as primitive types, while in C they are typedefs.
  • C++ comparison operators returns bool, while C returns int.
  • C++ supports overloading of operators.
  • C++ character constants have type char, while C character constants have type int.
  • C++ has specific cast operators (static_cast, dynamic_cast, const_cast and reinterpret_cast).
  • C++ adds mutable keyword to address the imperfect match between physical and logical constness.
  • C++ extends the type system with references.
  • C++ supports member functions, constructors and destructors for user-defined types to establish invariants and to manage resources.
  • C++ supports runtime type identification (RTTI), via typeid and dynamic_cast.
  • C++ includes exception handling.
  • C++ has std::vector as part of its standard library instead of variable-length arrays as in C.
  • C++ treats sizeof operator as compile time operation, while C allows it be a runtime operation.
  • C++ has new and delete operators, while C uses malloc and free library functions.
  • C++ supports object-oriented programming without extensions.
  • C++ does not require use of macros, unlike C, that uses them for careful information-hiding and abstraction (especially important for C code portability).
  • C++ supports per-line comments denoted by //. (C99 started official support for this comment system, and most compilers support this as an extension.)
  • C++ register keyword is semantically different to C's implementation.
Choosing C or C++

It is fairly common to find someone recommending the use of C instead of C++ (or vice versa), or complaining about some features of these languages. There is no decisive reason to prefer one language over the other in general. Most scientific studies that attempt to measure programmer productivity as a function of programming language rank C and C++ as essentially equal. C may be a better choice for some situations, for example kernel programming, like hardware drivers, or a relational database, which do not lend themselves well to object oriented programming. Another consideration is that C compilers are more ubiquitous so C programs can run on more platforms. Although both languages are still evolving, any new features added still maintain a high level of compatibility with old code, making the use of those new constructs a programmer's decision. It is not uncommon to establish rules in a project to limit the use of parts of a language (such as RTTI, exceptions, or virtual-functions in inner loops), depending on the proficiency of the programmers or the needs of the project. It is also common for new hardware to support lower level languages first. Due to C being simpler and lower level than C++, it is easier to check and comply with industry guidelines. Another benefit of C is that it is easier for the programmer to do low level optimizations, though most C++ compilers can guarantee nearly perfect optimizations automatically.

Ultimately it is the programmer's choice to decide what tool is the best for the job. It would be hard to justify selecting C++ for a project if the available programmers only know C. Even though in the reverse case it might be expected for a C++ programmer to produce functional C code, the mindset and experience needed are not the same. The same rationale is valid for C programmers and ASM. This is due to the close relations that exist in the language's structure and historical evolution.

One might think that using only the C subset of C++ compiled with a C++ compiler is the same as just using C, but in reality it can generate slightly different results depending on the compiler used. The Java programming language and C++ share many common traits. A comparison of the two languages follows here. For a more in-depth look at Java, see the Java Programming WikiBook.

Java

Java was initially created to support network computing on embedded systems. Java was designed to be extremely portable, secure, multi-threaded and distributed, none of which were design goals for C++. Java has a syntax familiar to C programmers, but direct compatibility with C was not maintained. Java was also specifically designed to be simpler than C++, but continues to evolve above that simplification.

During the decade between 1999 and 2009, especially in the part of the programming industry dedicated to enterprise solutions, “Coffee-based” languages, which rely on "virtual machines" that are familiar in Smalltalk, grew in prominence. This was a trade between performance and productivity, something that made perfect sense at the time where computing power and the need of simplified and more streamlined language that permitted not only easy adoption but a lower learning curve. There is enough similitude between the languages that the proficient C++ programmers can easily adapt to Java, that is still today in ways less complex and even in comparison more consistent in the adopted paradigms than C++.

This shift in interest has however decreased, mostly due to the evolution of the languages. C++ and Java evolution has merged much of the gap about the problems and limitations of both languages, the software requirements today have also shifted and fragmented more. Now we have specific requirements for mobile, data-center and desktop computing this makes the programming language selection an even more central issue.

C++ Java
Compatibility backwards compatible, including C backwards compatibility with previous versions
Focus execution efficiency developer productivity
Freedom trusts the programmer imposes some constraints to the programmer
Memory Management arbitrary memory access possible memory access only through objects
Code concise expression explicit operation
Type Safety type casting is restricted greatly only compatible types can be cast
Programming Paradigm procedural or object-oriented object-oriented
Operators operator overloading meaning of operators immutable
Preprocessor yes no
Main Advantage powerful capabilities of language feature-rich, easy to use standard library

Differences between C++ and Java are:

  • C++ parsing is somewhat more complicated than with Java; for example, Foo<1>(3); is a sequence of comparisons if Foo is a variable, but it creates an object if Foo is the name of a class template.
  • C++ allows namespace level constants, variables, and functions. All such Java declarations must be inside a class or interface.
  • const in C++ indicates data to be 'read-only,' and is applied to types. final in Java indicates that the variable is not to be reassigned. For basic types such as const int vs final int these are identical, but for complex classes, they are different.
  • C++ didn't support constructor delegation until the C++11 standard, and only very recent compilers support this.
  • C++ generates machine code that runs on the hardware, Java generates bytecode that runs on a virtual machine so with C++ you have greater power at the cost of portability.
  • C++, int main() is a function by itself, without a class.
  • C++ access specification (public, private) is done with labels and in groups.
  • C++ access to class members default to private, in Java it is package access.
  • C++ classes declarations end in a semicolon.
  • C++ lacks language level support for garbage collection while Java has built-in garbage collection to handle memory deallocation.
  • C++ supports goto statements; Java does not, but its labeled break and labeled continue statements provide some structured goto-like functionality. In fact, Java enforces structured control flow, with the goal of code being easier to understand.
  • C++ provides some low-level features that Java lacks. In C++, pointers can be used to manipulate specific memory locations, a task necessary for writing low-level operating system components. Similarly, many C++ compilers support inline assembler. In Java, assembly code can still be accessed as libraries, through the Java Native Interface. However, there is significant overhead for each call.
  • C++ allows a range of implicit conversions between native types, and also allows the programmer to define implicit conversions involving compound types. However, Java only permits widening conversions between native types to be implicit; any other conversions require explicit cast syntax. C++11 disallows narrowing conversions from initializer lists.
    • A consequence of this is that although loop conditions (if, while and the exit condition in for) in Java and C++ both expect a boolean expression, code such as if(a = 5) will cause a compile error in Java because there is no implicit narrowing conversion from int to boolean. This is handy if the code were a typo for if(a == 5), but the need for an explicit cast can add verbosity when statements such as if (x) are translated from Java to C++.
  • For passing parameters to functions, C++ supports both true pass-by-reference and pass-by-value. As in C, the programmer can simulate by-reference parameters with by-value parameters and indirection. In Java, all parameters are passed by value, but object (non-primitive) parameters are reference values, meaning indirection is built-in.
  • Generally, Java built-in types are of a specified size and range; whereas C++ types have a variety of possible sizes, ranges and representations, which may even change between different versions of the same compiler, or be configurable via compiler switches.
    • In particular, Java characters are 16-bit Unicode characters, and strings are composed of a sequence of such characters. C++ offers both narrow and wide characters, but the actual size of each is platform dependent, as is the character set used. Strings can be formed from either type.
  • The rounding and precision of floating point values and operations in C++ is platform dependent. Java provides a strict floating-point model that guarantees consistent results across platforms, though normally a more lenient mode of operation is used to allow optimal floating-point performance.
  • In C++, pointers can be manipulated directly as memory address values. Java does not have pointers—it only has object references and array references, neither of which allow direct access to memory addresses. In C++ one can construct pointers to pointers, while Java references only access objects.
  • In C++ pointers can point to functions or member functions (function pointers or functors). The equivalent mechanism in Java uses object or interface references. C++11 has library support for function objects.
  • C++ features programmer-defined operator overloading. The only overloaded operators in Java are the "+" and "+=" operators, which concatenate strings as well as performing addition.
  • Java features standard API support for reflection and dynamic loading of arbitrary new code.
  • Java has generics. C++ has templates.
  • Both Java and C++ distinguish between native types (these are also known as "fundamental" or "built-in" types) and user-defined types (these are also known as "compound" types). In Java, native types have value semantics only, and compound types have reference semantics only. In C++ all types have value semantics, but a reference can be created to any object, which will allow the object to be manipulated via reference semantics.
  • C++ supports multiple inheritance of arbitrary classes. Java supports multiple inheritance of types, but only single inheritance of implementation. In Java, a class can derive from only one class, but a class can implement multiple interfaces.
  • Java explicitly distinguishes between interfaces and classes. In C++ multiple inheritance and pure virtual functions makes it possible to define classes that function just as Java interfaces do.
  • Java has both language and standard library support for multi-threading. The synchronized keyword in Java provides simple and secure mutex locks to support multi-threaded applications. C++11 provides similar capabilities. While mutex lock mechanisms are available through libraries in previous versions of C++, the lack of language semantics makes writing thread safe code more difficult and error prone.
Memory management
  • Java requires automatic garbage collection. Memory management in C++ is usually done by hand, or through smart pointers. The C++ standard permits garbage collection, but does not require it; garbage collection is rarely used in practice. When permitted to relocate objects, modern garbage collectors can improve overall application space and time efficiency over using explicit deallocation.
  • C++ can allocate arbitrary blocks of memory. Java only allocates memory through object instantiation. (Note that in Java, the programmer can simulate allocation of arbitrary memory blocks by creating an array of bytes. Still, Java arrays are objects.)
  • Java and C++ use different idioms for resource management. Java relies mainly on garbage collection, while C++ relies mainly on the RAII (Resource Acquisition Is Initialization) idiom. This is reflected in several differences between the two languages:
    • In C++ it is common to allocate objects of compound types as local stack-bound variables that are destructed when they go out of scope. In Java compound types are always allocated on the heap and collected by the garbage collector (except in virtual machines that use escape analysis to convert heap allocations to stack allocations).
    • C++ has destructors, while Java has finalizers. Both are invoked prior to an object's deallocation, but they differ significantly. A C++ object's destructor must be implicitly (in the case of stack-bound variables) or explicitly invoked to deallocate the object. The destructor executes synchronously at the point in the program at which the object is deallocated. Synchronous, coordinated uninitialization and deallocation in C++ thus satisfy the RAII idiom. In Java, object deallocation is implicitly handled by the garbage collector. A Java object's finalizer is invoked asynchronously some time after it has been accessed for the last time and before it is actually deallocated, which may never happen. Very few objects require finalizers; a finalizer is only required by objects that must guarantee some clean up of the object state prior to deallocation—typically releasing resources external to the JVM. In Java safe synchronous deallocation of resources is performed using the try/finally construct.
    • In C++ it is possible to have a dangling pointer – a reference to an object that has been destructed; attempting to use a dangling pointer typically results in program failure. In Java, the garbage collector won't destruct a referenced object.
    • In C++ it is possible to have an object that is allocated, but unreachable. An unreachable object is one that has no reachable references to it. An unreachable object cannot be destructed (deallocated), and results in a memory leak. By contrast, in Java an object will not be deallocated by the garbage collector until it becomes unreachable (by the user program). (Note: weak references are supported, that work with the Java garbage collector to allow for different strengths of reachability.) Garbage collection in Java prevents many memory leaks, but leaks are still possible under some circumstances.
Libraries
  • C++ standard library provides a limited set of basic and relatively general purpose components. Java has a considerably larger standard library. This additional functionality is available for C++ by (often free) third party libraries, but third party libraries do not provide the same ubiquitous cross-platform functionality as standard libraries.
  • C++ is mostly backward compatible with C, and C libraries (such as the APIs of most operating systems) are directly accessible from C++. In Java, the richer functionality of its standard library provides cross-platform access to many features typically only available in platform-specific libraries. Direct access from Java to native operating system and hardware functions requires the use of the Java Native Interface.
Runtime
  • C++ is normally compiled directly to machine code that is then executed directly by the operating system. Java is normally compiled to byte-code that the Java virtual machine (JVM) then either interprets or JIT compiles to machine code and then executes.
  • Due to the lack of constraints in the use of some C++ language features (e.g. unchecked array access, raw pointers), programming errors can lead to low-level buffer overflows, page faults, and segmentation faults. The Standard Template Library, however, provides higher-level abstractions (like vector, list and map) to help avoid such errors. In Java, such errors either simply cannot occur or are detected by the JVM and reported to the application in the form of an exception.
  • In Java, bounds checking is implicitly performed for all array access operations. In C++, array access operations on native arrays are not bounds-checked, and bounds checking for random-access element access on standard library collections like std::vector and std::deque is optional.
Miscellaneous
  • Java and C++ use different techniques for splitting up code in multiple source files. Java uses a package system that dictates the file name and path for all program definitions. In Java, the compiler imports the executable class files. C++ uses a header file source code inclusion system for sharing declarations between source files.
  • Templates and macros in C++, including those in the standard library, can result in duplication of similar code after compilation. Second, dynamic linking with standard libraries eliminates binding the libraries at compile time.
  • C++ compilation features a textual preprocessing phase, while Java does not. Java supports many optimizations that mitigate the need for a preprocessor, but some users add a preprocessing phase to their build process for better support of conditional compilation.
  • In Java, arrays are container objects that you can inspect the length of at any time. In both languages, arrays have a fixed size. Further, C++ programmers often refer to an array only by a pointer to its first element, from which they cannot retrieve the array size. However, C++ and Java both provide container classes (std::vector and java.util.ArrayList respectively) that are re-sizable and store their size. C++11's std::array provides fixed-size arrays with a similar efficiency to classic arrays, functions to return the size, and optional bounds-checking.
  • Java's division and modulus operators are well defined to truncate to zero. C++ does not specify whether or not these operators truncate to zero or "truncate to -infinity". -3/2 will always be -1 in Java, but a C++ compiler may return either -1 or -2, depending on the platform. C99 defines division in the same fashion as Java. Both languages guarantee that (a/b)*b + (a%b) == a for all a and b (b != 0). The C++ version will sometimes be faster, as it is allowed to pick whichever truncation mode is native to the processor.
  • The sizes of integer types is defined in Java (int is 32-bit, long is 64-bit), while in C++ the size of integers and pointers is compiler-dependent. Thus, carefully-written C++ code can take advantage of the 64-bit processor's capabilities while still functioning properly on 32-bit processors. However, C++ programs written without concern for a processor's word size may fail to function properly with some compilers. In contrast, Java's fixed integer sizes mean that programmers need not concern themselves with varying integer sizes, and programs will run exactly the same. This may incur a performance penalty since Java code cannot run using an arbitrary processor's word size. C++11 offers types such as uint32_t with guaranteed sizes, but compilers are not forced to provide them on hardware which has no native support for the size.
Performance

Computing performance is a measure of resource consumption when a system of hardware and software performs a piece of computing work such as an algorithm or a transaction. Higher performance is defined to be 'using fewer resources'. Resources of interest include memory, bandwidth, persistent storage and CPU cycles. Because of the high availability of all but the latter on modern desktop and server systems, performance is colloquially taken to mean the least CPU cycles; which often converts directly into the least wall clock time. Comparing the performance of two software languages requires a fixed hardware platform and (often relative) measurements of two or more software subsystems. This section compares the relative computing performance of C++ and Java on common operating systems such as Windows and Linux.

Early versions of Java were significantly outperformed by statically compiled languages such as C++. This is because the program statements of these two closely related languages may compile to a small number of machine instructions with C++, while compiling into a larger number of byte codes involving several machine instructions each when interpreted by a Java JVM. For example:

Java/C++ statement C++ generated code Java generated byte code
vector[i]++; mov edx,[ebp+4h]

mov eax,[ebp+1Ch]
inc dword ptr [edx+eax*4]

aload_1

iload_2
dup2
iaload
iconst_1
iadd
iastore

While this may still be the case for embedded systems because of the requirement for a small footprint, advances in just in time (JIT) compiler technology for long-running server and desktop Java processes has closed the performance gap and in some cases given the performance advantage to Java. In effect, Java byte code is compiled into machine instructions at run time, in a similar manner to C++ static compilation, resulting in similar instruction sequences.

C++ is still faster in most operations than Java at the moment, even at low-level and numeric computation. For in-depth information you could check Performance of Java versus C++. It's a bit pro-Java but very detailed.

Comparing Imports vs Includes

There can be some confusion among C and C++ programmers about how imports work, and conversely among Java programmers, for example, about the proper use of include files. In a comparison between Symbol-table imports in modern Programming languages with the use of #includes, like in C and C++. Although, both of these techniques are solutions to the same problem, namely compiling across multiple source files, they are vastly different techniques. Since nearly all modern Compilers consist of essentially the same stages of compilation, the biggest difference can be explained by the fact that includes occur in the Lexical-analysis stage of compilation, whereas imports are not done until the semantic analysis stage.

Advantages of imports

  • Imports do not duplicate any lexical analysis effort, which generally results in faster compilation for larger projects.
  • Imports do not require splitting code into separate files for declaration/implementation.
  • Imports better facilitate distribution of Object code, rather than Source code.
  • Imports can allow circular dependencies between source files.
  • Imports implicitly carry a mechanism for resolving symbol collisions when more than one symbol table defines the same symbol.

Disadvantages of imports

  • When an importable module is altered, since there is no separation of definition and implementation, all dependent modules must be recompiled, which can entail significant compilation times in large projects.
  • Imports require a standard mechanism for defining a symbol table in object code. Whether this limitation is truly a weakness is debatable, as a standard symbol table is useful for a number of other reasons.
  • Imports require a method for discovering symbol tables at compile time (such as the classpath in Java). When, however, there exists a standard method for doing this, this is not necessarily any more complicated than specifying the locations of include files.
  • When circular dependencies are allowed, semantic analysis of several interdependent source files may need to be interleaved.
  • Unless the language includes support for Partial types, languages with imports instead of includes require all source code for a class to be in a single source file.

Advantages of includes

  • With includes, there is no interdependence between source files at the semantic analysis stage. This means that at this stage, each source file can be compiled as an independent unit.
  • Separating definition and implementation into header and source files reduce dependencies and allows recompilation of only the affected source file, and no other files, when implementation details are altered.
  • Include files, used in combination with other Preprocessor features, allow for nearly arbitrary lexical processing.
  • Although the practice is not widespread, includes can provide rudimentary support for several modern language features (such as Mixins and aspects) if the language itself does not support them.
  • Includes are not part of the syntax of the underlying language, but rather part of a preprocessor syntax. There are disadvantages to this (another language to learn), but there are also advantages. The preprocessor syntax, and in some cases include files themselves, may be shared among several different languages.

Disadvantages of includes

  • Includes and the requisite preprocessor can require more passes in the lexical-analysis stage of compilation.
  • Repeated compilation of header files included multiple times in a large project can be notoriously slow. This can be mitigated, however, through the use of Pre-compiled headers.
  • Proper use of header files, particularly declarations of global variables, can be tricky for beginners.
  • Because includes generally require the location of the included file to be specified in the source code, environment variables are often needed to provide part of the include file path. Even worse, this functionality is not supported in a standard way across all compilers.

A comparing example that compares C++ with Java exists here.

C#

C# (pronounced "See Sharp") is a multi-purpose computer programming language catering to all development needs using Microsoft .NET Framework.

Note:
C#'s chief designer was Anders Hejlsberg. Before joining Microsoft in 1996, Hejlsberg worked at Borland developing Turbo Pascal and Delphi. At Microsoft he worked as an architect for J++ and is still a key participant in the development of the .NET framework.

We already covered Java. C# is very similar, in that it takes the basic operators and style of C++ but forces programs to be type safe, in that it executes the code in a controlled sandbox called the virtual machine. As such, all code must be encapsulated inside an object, among other things. C# provides many additions to facilitate interaction with Microsoft's Windows, COM, and Visual Basic. C# is a ECMA and ISO standard.

C# was a response from Microsoft to the (then Sun-developed) Java language that was beginning to have a major impact in the enterprise. After their failed attempt to push J++ into the market and in legal confrontation with Sun, Microsoft shifted their focus to managed languages, even as a way to maintain the relevance of Visual Basic with a large developer base, and so with the announcement of Windows "Longhorn" project (which became Windows Vista) the push to managed languages and its integration with the Windows Operating System began, with the belief that from there on "all new Windows APIs would be managed".

Today however, Microsoft seems to have finally realized that managed languages, even looking on the adoption of Java, lack the requirements to develop an Operating System. Microsoft even started a C#-based OS to test the premise, but came to a realization that all major software projects, even utilities that come with the Windows OS, are mostly C or C++ based. Even if managed code still has a place, C and C++ have finally been accepted as the core languages of the software industry for the foreseeable future. In Windows, this is being seen as the "C++ Renaissance" after the long age of darkness that the marketing machine had engulfed developers with.

Some similarities between C# and C++
  • They both are Object-Oriented languages, meaning that they use classes, inheritance, and polymorphism (though with different syntaxes). This could be considered a difference here, as C# is considered a purely object-oriented language while C++ supports various other paradigms.
  • Both C# and C++ are compiled languages, meaning that source code must be converted to a binary format before it can be run.
Some differences between C# and C++
  • C++ compiles into machine code, whereas C# compiles to an intermediate representation which is run on the Common Language Runtime (CLR) virtual machine.
  • C# does not typically use pointers while in C++ they are used frequently. C# only permits the usage of pointers in unsafe mode.
  • C# is mostly used by Windows which is not the most convenient, but C++ can be used on any platform with no problems.
  • C++ can make stand-alone applications whereas C# cannot.
  • C# supports foreach loops but C++ does not.
  • C++ supports multiple inheritances but C# does not support multiple inheritances
  • C# has two additional modifiers besides private, public and protected which are internal and protected internal.
  • C++ is more used for application development because there is a direct interaction with hardware and better performance requirement but C# programming is mostly used in web and desktop applications which performance is not as important.


Disadvantages of C# compared to C++
  • Limitation: With C#, features like multiple inheritance from classes (C# implements a different approach called Multiple Implementation, where a class can implement more than one interface), declaring objects on the stack, deterministic destruction (allowing for RAII) and allowing default arguments as function parameters (in C# versions < 4.0) will not be available.
  • Performance (speed and size): Applications built in C# may not perform as well when compared with native C++. C# has an intrusive garbage collector, reference tracking and other overheads with some of the framework services. The .NET framework alone has a big runtime footprint (~30 Mb of memory), and requires that several versions of the framework be installed.
  • Flexibility: Due to the dependency on the .NET framework, operating system level functionality (system level APIs) is buffered by a generic set of functions that will reduce some freedoms.
  • Runtime Redistribution: Programs need to be distributed with the .NET framework (pre-Windows XP or non-Windows machines), similar to the issue with the Java language, with all the normal upgrade requirements attached.
  • Portability: The .NET complete framework is only available on the Windows OS, but there are open-source versions that provide most of the core functionality, that also support the GNU-Linux OS, like MONO and Portable.NET http://www.gnu.org/software/dotgnu/pnet.html. There are ECMA and ISO .NET standards for example for C# and the CLI extension to C++.
Advantages of C# compared to C++

There are several shortcomings to C++ that are resolved in C#:

  • One of the more subtle ones is the use of reference variables as function arguments. When a code maintainer is looking at C++ source code, if a called function is declared in a header somewhere, the immediate code does not provide any indication that an argument to a function is passed as a non-const reference. An argument passed by reference could be changed after calling the function whereas an argument passed by value or passed as const cannot be changed. A maintainer unfamiliar with the function and looking for the location of an unexpected value change of a variable would additionally need to examine the header file for the function in order to determine whether or not that function could have changed the value of the variable. C# insists that the ref keyword be placed in the function call (in addition to the function declaration), thereby cluing the maintainer in that the value could be changed by the function.
  • Another one is the memory management, C# runs in a virtual machine which has the ability to handle memory management but in C++ the developer needs the handle the memory themselves. C# has a garbage collector that de-allocates memory pointed by objects which are not in use.

An example comparing C++ with C# can be found here.

Managed C++ (C++/CLI)

Managed C++ is a shorthand notation for Managed Extensions for C++, which are part of the .NET framework from Microsoft. This extension of the C++ language was developed to add functionality like automatic garbage collection and heap management, automatic initialization of arrays, and support for multidimensional arrays, simplifying all those details of programming in C++ that would otherwise have to be done by the programmer.

Managed C++ is not compiled to machine code. Rather, it is compiled to Common Intermediate Language, which is an object-oriented machine language and was formerly known as MSIL.

#include<iostream.h>
#include<math.h>
 void main()
 {
	int choose;
	double Area,Length,Width,Radius,Base,Height;
	cout<<"circle(1)";
	cout<<"Square(2)";
	cout<<"Rectangle(3)";
	cout<<"Triangle(4)";
	cout<<"select 1,2,3,4:";
 loop:
	cin>>choose;
 if(choose=='1')
  {
		double Radius;
		const double pi=3.142;
		cout<<"Enter Radius";
		cin>>Radius;
		Area=pi*pow(Radius,2);
  }
  else if(choose=='2')
  {
		double Length;
		cout<<"Enter Length:";
		cin>>Length;
		Area= pow(1,2);
  }
  else if (choose=='3')
  {
		double Length,Width;
		cout<<"Enter Length:";
		cin>>Length;
		cout<<"Enter Width:";
		cin>>Width;
		Area=Length*Width;
  }
  else if(choose=='4')
  {
		double Base,Height;
		cout<<"Enter Base:";
		cin>>Base;
		cout<<"Enter Height:";
		cin>>Height;
		Area=Height*Base/2;
  }
  else
  {
		cout<<"Select only 1,2,3,4:";
		goto loop;
  }
  cout<<"Area:"<<Area;
 }

D

The D programming language, was developed in-house by Digital Mars, a small US software company, also known for producing a C compiler (known over time as Datalight C compiler, Zorland C and Zortech C), the first C++ compiler for Windows (originally known as Zortech C++, renamed to Symantec C++, and now Digital Mars C++ (DMC++) and various utilities (such as an IDE for Windows that supports the MFC library).

Originally designed by Walter Bright it has, since 2006, had the collaboration of Andrei Alexandrescu and other contributors. While D originated as a re-engineering of C++ and is predominantly influenced by it, D is not a variant of C++. D has redesigned some C++ features and has been influenced by concepts used in other programming languages, such as Java, C# and Eiffel. As such, D is an evolving open-source system programming language, supporting multiple programming paradigms.

It supports the procedural, generic, functional and object-oriented paradigms. Most notably it provides very powerful, yet simple to use, compile-time meta-programming facilities.

It is designed to offer a pragmatic combination of efficiency, control, and modeling power, with safety and programmer productivity. Another of its goals is to be easy to use for beginners and to offer advanced capabilities when experienced programmers need them.

Supported platforms

D is officially supported on Windows, Linux, OSX and FreeBSD on x86 and x86_64. Support in other platforms (Android, iOS and Solaris) and hardware (ARM, MIPS and Power-PC) is work-in-progress.

Compilers

There 3 production ready compilers: DMD, GDC and LDC.

  • DMD is the reference implementation. The other two compilers share DMD's frontend. It offers very fast compilation, useful at development-time.
  • GDC uses GCC's backend for code-generation. It integrates well with the GNU toolchain.
  • LDC uses LLVM's backend. It can integrate well with other parts of the LLVM toolchain.
Interfacing with C and C++

D can link directly with C and C++ (*) static and shared libraries without any wrappers or additional overhead (compared to C and C++). Supported subset of C++ platform specific ABI (e.g. GCC and MSVC):

  • C++ name mangling conventions, like namespaces, function names and other
  • C++ function calling conventions
  • C++ virtual function table layout for single inheritance

Generally D uses the platform linker on each platform (ld.bfd, ld.gold, etc. on Linux), the exception being Windows, where Optlink is used by default. MSVC link.exe is also supported, but the Windows SDK must be first downloaded.

D features missing from C and C++

Some the new features that a C/C++ programmer will find are:

  • Design by introspection - one can design a templated class or struct to inspect its template arguments at compile-time for different capabilities and then adapts to them. For example, a composable allocator design can check if the parent allocator provides reallocation and efficiently delegate to it, or fallback to implementing reallocation with malloc() and free(), or not offer it at all. The benefit of doing this at compile-time is that the user of the said allocator can know if he should use reallocate(), instead of getting mysterious run-time errors.
  • True modules
  • Order of declaration and imports (#include-s in C++ terms) is insignificant. There is no need to pre-declare anything. You can rearrange things without change in meaning
  • Faster compilation - C++'s compilation model is inherently slow. Additionally compilers like DMD have further optimizations
  • More powerful conditional compilation without preprocessor
  • pure functions - side-effect free functions that are allowed to have internal mutation
  • Immutability - it is guaranteed that variables declared as immutable can be accessed safely from multiple threads (without locking and race-conditions)
  • Design by contract
  • Universal function call syntax (UFCS) - allow the free function void copyTo(T)(T[] src, T[] dst) to be called like this: sourceArray.copyTo(destinationArray)
  • Built-in unit testing
  • Garbage collection (optional)
  • scope control flow statement (partially emulated in C++ with the ScopeGuard idiom)

First class:

  • Dynamic arrays
int[] array; //declare empty array variable
array ~= 42; //append 42 to the array; array.equals([ 42 ]) == true
array.length = 5; //set the length to 5; will reallocate if needed
int[] other = new int[5]; // declare an array of five elements
other[] = 18; // fill the array with 18; other.equals([18, 18, 18, 18, 18]) == true
array[] = array[] * other[]; //array[i] becomes array[i] * other[i]
array[$ - 1] = -273; // set the last element to -273; when indexing an array the $ context variable is translated to array.length
int[] s = array[2 .. $]; // s points to the last 3 elements of array (no copying occurs).
  • Unicode strings
string s1 = "Hello "; // array of immutable UTF8 chars
immutable(char)[] s2 = "World "; // `s2` has the same type as `s1`
string s3 = s1 ~ s2; // set `s3` to point to the result of concatenating `s1` with `s2`
char[] s4 = s3.dup; // `s4` points to the mutable array "Hello World "
s4[$-1] = '!'; // change the last character in the string
s4 ~= "<-> Здравей, свят!"; // append Cyrillic characters that don't fit in a single UTF-8 code-unit

import std.conv : to;
wstring ws = s4.to!wstring; //convert s4 to an array of immutable UTF16 chars

foreach (dchar character; ws) // iterate over ws; 'character' is an automatically transcoded UTF32 code-point
{
    import std.stdio : writeln; // scoped selective imports	
    character.writeln(); //write each character on a new line
}

You can find a runnable example at dpaste.dzfl.pl - online compiler and collaboration tool dedicated to D.

  • Associative arrays
struct Point { uint x; uint y; } // toHash is automatically generated by the compiler, if not user provided
Point[string] table; // hashtable string -> Data
table["Zero"] = Point(0, 0);
table["BottomRight"] = Point(uint.max, uint.max);
  • Nested functions
  • Closures (C++11 added lambda functions, but lambda functions that capture variables by reference are not allowed to escape the function they were created in).
  • Inner classes
C++ features missing from D
  • Preprocessor
  • Polymorphic types with non-virtual destructor
  • Polymorphic value-types - in D struct-s are value types without support for inheritance and virtual functions and class-es are reference types that support inheritance and virtual functions
  • Multiple inheritance - D classes offers only Java and C# style multiple implementation of interfaces. Instead, for code reuse D favors composition, mixins and alias this

See the D Programming book for more details.

Chapter summary

  1. Introducing C++  
  2. Programming languages  
    1. Programming paradigms   - the versatility of C++ as a multi-paradigm language, concepts of object-oriented programming (objects and classes, inheritance, polymorphism).
  3. Comparisons   - to other languages, relation to other computer science constructs and idioms.
    1. with C  
    2. with Java  
    3. with C#  
    4. with Managed C++ (C++/CLI)  
    5. with D  

  1. "C++ is the third most popular programming language according to the TIOBE index". September 2020.