Skip to main content
Bethemesh
HistoryComputing history

C++: from C with Classes to a general-purpose language

From C with Classes to modern C++, discover how the language reconciled abstraction, generic programming, compatibility, and performance control.

Published 10 August 2026Reading : 21 minBy Bethemesh Team
Beginner
C++: from C with Classes to a general-purpose language
Show contents
  1. Before C++: the success of C
  2. Bjarne Stroustrup and the influence of Simula
  3. 1979: “C with Classes”
  4. Cfront: translating C++ into C
  5. 1983: C with Classes becomes C++
  6. 1985: the first commercial release
  7. Object-oriented programming becomes central
  8. “Zero-overhead abstractions”
  9. Deterministic resource management
  10. Templates profoundly change C++
  11. The birth of the STL
  12. Why is the STL so important?
  13. Standardization becomes essential
  14. C++98: the language becomes an international standard
  15. The 2000s: power and a reputation for complexity
  16. Java offers another answer
  17. C++11: the language is reborn
  18. Move semantics
  19. Smart pointers change programming practices
  20. Modern C++: avoiding “historical” C++
  21. C++14: consolidating C++11
  22. C++17: enriching the language and its library
  23. C++20: concepts, ranges, and coroutines
  24. C++23 and continuous evolution
  25. Why not simply remove old features?
  26. Is C++ really compatible with C?
  27. A multi-paradigm language
  28. Metaprogramming: when the compiler computes
  29. Why is C++ still used?
  30. Performance
  31. Predictability
  32. Ecosystem
  33. Interoperability
  34. Compilers
  35. Portability
  36. Video games and 3D engines
  37. Browsers and complex software
  38. Embedded systems and hardware constraints
  39. Finance, scientific computing, and infrastructure
  40. The cost of this power: complexity
  41. Memory safety becomes a major issue
  42. C++ compared with newer languages
  43. Why has C++ not been completely redesigned?
  44. The role of the ISO committee
  45. C++ is no longer the language of 1985
  46. C++ and the idea of a “general-purpose language”
  47. A language shaped by its constraints
  48. From C with Classes to modern C++
  49. Key takeaways
  50. Frequently asked questions
  51. Who created C++?
  52. What was C++ originally called?
  53. Why is the language called C++?
  54. Is C++ simply an object-oriented version of C?
  55. What is the difference between C and C++?
  56. Why is C++11 so important?
  57. Does C++ use garbage collection?
  58. Is C++ still used today?
  59. Why is C++ considered difficult?
  60. Will C++ be replaced?

C++ occupies a unique place in the history of programming languages. Born in the late 1970s at Bell Labs, it did not set out to radically replace existing tools. Its ambition was more subtle: to add powerful abstraction mechanisms without giving up the control, efficiency, and closeness to the machine that had made the C language so successful.

This tension has accompanied C++ since its beginnings.

The language must make it possible to build large, structured software systems while remaining suitable for environments where performance, memory, and hardware resources matter. It must evolve without making an enormous amount of existing code unusable. It must support several programming styles without imposing a single model.

More than forty years after its beginnings, C++ is still used in game engines, operating systems, browsers, scientific software, financial infrastructure, embedded applications, and many components where performance is essential.

Its history is therefore one of a permanent compromise between abstraction and control.

Before C++: the success of C

To understand C++, we first need to understand C.

In the early 1970s, Dennis Ritchie developed C at Bell Labs in the context of the creation of Unix. The language offered a remarkable balance: it made it possible to write relatively portable code while giving programmers precise control over memory and machine resources.

C quickly became a major language for systems programming.

Our article on the history of the C language looks at this evolution in greater detail.

But as programs grew larger, a difficulty became increasingly apparent: how could complex systems be organized without losing the performance and control offered by C?

C allowed developers to structure code using functions, structures, and modules, but it did not natively provide the abstraction mechanisms that some research languages were already exploring.

This was precisely the problem that interested a young Danish researcher: Bjarne Stroustrup.

Bjarne Stroustrup and the influence of Simula

In the late 1970s, Bjarne Stroustrup was working on his doctoral thesis at the University of Cambridge.

Among the languages he used was Simula, developed in Norway during the 1960s and often regarded as one of the major ancestors of object-oriented programming.

Simula offered powerful concepts: classes, objects, inheritance, and virtual methods.

For Stroustrup, these abstractions made it considerably easier to model complex systems.

But he also encountered a limitation: the performance available with the tools he was using did not meet his needs.

When he joined Bell Labs in 1979, he worked on problems related to distributed systems. He wanted the abstraction capabilities of Simula while retaining the efficiency of C.

The founding idea behind C++ can almost be summarized as follows:

what if we could have Simula-style classes without giving up the performance and ecosystem of C?

The biography of Bjarne Stroustrup explores his career and the design choices that shaped the language in more detail.

1979: “C with Classes”

The first project was not called C++.

Starting in 1979, Stroustrup developed a language named C with Classes.

The name described the initial intention quite well.

The goal was not to start again from scratch, but to extend C with mechanisms that made it easier to structure programs.

C with Classes introduced features including:

  • classes;
  • constructors and destructors;
  • access control;
  • certain forms of inheritance;
  • default arguments;
  • functions integrated into the class model.

The objective was already to help programmers express abstractions without imposing unnecessary runtime cost.

This idea would become one of the historical principles of C++: you should not pay for what you do not use.

Cfront: translating C++ into C

The early development of C++ benefited from a pragmatic strategy.

Rather than immediately building an entirely independent compilation infrastructure, Stroustrup developed Cfront.

Cfront translated C with Classes, and later C++, into C code.

The result could then be compiled using C compilers already available on different platforms.

This approach had several advantages.

It made experimentation easier.

It allowed the new language to benefit from the existing C ecosystem.

It also demonstrated that a language offering richer abstractions could be transformed into code that remained sufficiently close to low-level mechanisms.

Cfront played an important role during the early years of C++, before native compilers gradually took over.

1983: C with Classes becomes C++

In the early 1980s, the language evolved rapidly.

In 1983, it received its definitive name: C++.

The name was proposed by Rick Mascitti.

In C, the ++ operator increments a value.

“C++” therefore humorously suggests an improved or incremented C.

The name perfectly reflects the philosophy of the project: C++ maintains strong continuity with C while adding new capabilities.

Around this period, several important elements appeared or became more established:

  • virtual functions;
  • function overloading;
  • operator overloading;
  • references;
  • constants;
  • stronger type checking.

The language was beginning to take the form by which it would become recognizable.

1985: the first commercial release

In 1985, the first edition of The C++ Programming Language, written by Bjarne Stroustrup, was published.

That same year, the first commercial version of C++ became available.

This period marked the language’s move beyond the experimental environment of Bell Labs.

C++ began to be adopted for real industrial projects.

Its main argument was attractive: developers familiar with C could build more structured abstractions without giving up control over resources.

That promise was particularly appealing in fields where the cost of abstractions had to remain predictable.

Object-oriented programming becomes central

During the 1980s and 1990s, object-oriented programming grew rapidly.

The general idea was to organize programs around objects combining data and behavior.

C++ contributed greatly to the spread of this approach.

Classes, encapsulation, inheritance, and polymorphism made it possible to represent hierarchies and define common interfaces.

Virtual functions, in particular, played an essential role.

They made it possible to select at runtime the function corresponding to the actual type of an object.

This capability enables dynamic polymorphism.

But C++ retained a distinctive philosophy: these mechanisms were not mandatory.

A program could use classes without inheritance, rely on free functions, manipulate memory directly, or adopt other styles.

C++ therefore never became an exclusively object-oriented language.

To place these concepts in their historical context, our article on the history of object-oriented programming traces the path from Simula and Smalltalk to modern languages.

“Zero-overhead abstractions”

One idea gradually became emblematic of the C++ philosophy: zero-overhead abstractions.

The principle can be summarized as follows:

  • what you do not use should not cost you;
  • what you do use should not be significantly less efficient than an equivalent hand-written implementation.

This ambition explains many of the language’s design choices.

C++ aims to let developers write high-level abstractions while giving the compiler enough information to produce highly efficient code.

This distinguishes C++ from languages that place greater emphasis on a simpler execution model or delegate more resource management to a virtual machine or garbage collector.

This philosophy is extremely powerful.

It also contributes to the complexity of the language.

Deterministic resource management

C++ developed a particularly important model around constructors and destructors.

When an object is created, its constructor can acquire a resource.

When the object leaves its scope, its destructor can release that resource automatically.

This idea gave rise to a practice known as RAII (Resource Acquisition Is Initialization).

The resource does not have to be memory.

It can be:

  • a file;
  • a lock;
  • a connection;
  • a system descriptor;
  • a graphics resource;
  • a block of memory.

The benefit is significant: the lifetime of a resource can be tied to the lifetime of an object.

This deterministic management remains one of the most important characteristics of modern C++.

Templates profoundly change C++

In the late 1980s and early 1990s, C++ moved in a direction that went far beyond object orientation.

Templates made it possible to write generic code.

Instead of writing a different function for every data type, a programmer could define an operation parameterized by a type.

For example, a generic function could express the idea of searching for an element without depending directly on whether that element was an integer, a string, or another compatible type.

This capability opened the way to generic programming.

It would become just as important to the identity of C++ as classes and inheritance.

This was a crucial turning point: reducing C++ to “C with object-oriented programming” became increasingly inaccurate.

The birth of the STL

One of the major events in the history of the language was the integration of the Standard Template Library, or STL.

The STL largely emerged from the work of Alexander Stepanov and his collaborators on generic programming.

Its approach is based on a powerful idea: separate data structures from the algorithms that manipulate them through generic interfaces.

This gave developers concepts that became familiar in C++:

  • vector;
  • list;
  • map;
  • iterators;
  • algorithms such as sorting and searching.

Instead of creating a different sorting function for every container, a generic algorithm can operate on compatible iterators.

This design profoundly influenced C++.

The standard library gradually became an essential part of the language as it is actually used.

Why is the STL so important?

The STL demonstrates that it is possible to combine:

  • genericity;
  • reusability;
  • abstraction;
  • performance.

A well-designed abstraction does not necessarily imply a heavy runtime penalty.

The compiler can instantiate and optimize generic code for the types actually used.

This philosophy would permanently strengthen C++ culture.

The language was no longer merely C enriched with classes.

It became a multi-paradigm environment capable of combining procedural, object-oriented, and generic programming.

Standardization becomes essential

As C++ spread, multiple compilers appeared.

An obvious problem emerged: without a common standard, each implementation risked developing its own dialect.

Standardization became essential.

An international standardization process was established within ISO.

The objective was to define the language and its standard library precisely so that conforming programs could be moved more easily between implementations.

This process resulted in the first major international C++ standard in 1998.

C++98: the language becomes an international standard

C++98 was a fundamental milestone.

For the first time, the language had a complete ISO standard.

It formalized many features developed during the previous years and integrated the STL into the standard library.

Standardized C++ now had a common foundation for compiler vendors and developers.

A correction to the standard, commonly known as C++03, followed a few years later.

For a long period, however, C++98/03 remained the main reference.

This stability encouraged industrial adoption.

It also came at a cost: while computing practices evolved rapidly, the language itself sometimes appeared to move slowly.

The 2000s: power and a reputation for complexity

By the early 2000s, C++ was extremely widespread.

It was used in desktop software, video games, systems, financial applications, scientific tools, and a wide range of infrastructure.

But its reputation also became more mixed.

The language had accumulated several decades of features.

It retained strong compatibility with C and with older C++ code.

Manual memory management remained common.

Errors such as buffer overflows, invalid pointers, double frees, and memory leaks could cause bugs that were difficult to diagnose.

Templates sometimes generated intimidating error messages.

The syntax contained many special cases.

C++ was powerful, but that power demanded significant discipline.

Java offers another answer

In the 1990s, Java appeared with a different philosophy.

The language adopted syntax familiar to C and C++ developers, but removed or constrained several mechanisms considered dangerous or overly complex.

It relied notably on a virtual machine and garbage collection to automate part of memory management.

This difference illustrates two approaches.

C++ strongly favors control, compatibility, and the ability to optimize close to the underlying resources.

Java accepts more runtime abstraction in exchange for a more uniform environment and more automated memory management.

Our article on the history of Java makes it possible to compare these trajectories.

The two languages do not address exactly the same constraints, and their coexistence shows that there is no single way to design a general-purpose language.

C++11: the language is reborn

The next major transformation arrived in 2011.

The C++11 standard was so important that it is often regarded as the beginning of modern C++.

Many features appeared or became genuinely practical:

  • auto for type inference;
  • lambda expressions;
  • rvalue references;
  • move semantics;
  • standard smart pointers;
  • nullptr;
  • range-based for loops;
  • improved support for concurrent programming;
  • constexpr;
  • initializer lists;
  • variadic templates.

This list represents only part of the changes.

C++11 did not merely add features.

It changed the recommended way of writing C++.

Move semantics

Among the innovations of C++11, move semantics is particularly representative of the language’s philosophy.

Imagine an object containing a large amount of data.

Copying it can be expensive.

But if the source object will no longer be used, it may be possible to transfer its resources directly to the new object instead of copying everything.

Rvalue references and move operations make it possible to express this situation.

The language therefore gains a more expressive abstraction without unnecessarily sacrificing performance.

This is an excellent example of the historical goal of C++: enabling high-level abstractions while retaining precise control over their cost.

Smart pointers change programming practices

For a long time, learning C++ often meant learning new and delete very early.

Modern C++ encourages a different approach.

Types such as:

  • std::unique_ptr;
  • std::shared_ptr;
  • std::weak_ptr

make it possible to express ownership and object lifetimes more explicitly.

Combined with RAII and standard-library containers, they greatly reduce the need to manage dynamic memory directly in ordinary application code.

This does not turn C++ into a garbage-collected language.

The distinction matters.

Resource release generally remains deterministic, but it can be automated by the types themselves.

Modern C++: avoiding “historical” C++

From C++11 onward, an idea became increasingly widespread: modern C++ code can look very different from the style commonly taught in the 1990s.

Recommended practices include:

  • preferring objects with automatic lifetime;
  • using standard containers rather than manual arrays where appropriate;
  • using smart pointers to express ownership;
  • avoiding unnecessary explicit allocations;
  • using standard-library algorithms and abstractions;
  • limiting dangerous conversions;
  • making greater use of the type system.

This evolution matters.

Part of C++’s reputation comes from older practices that remain technically possible but no longer necessarily represent the recommended way to write new programs.

C++14: consolidating C++11

The C++14 standard was intentionally less revolutionary.

It improved and completed mechanisms introduced in 2011.

The objective was notably to make some features simpler and more consistent.

C++ was entering a more regular development rhythm.

Instead of waiting more than a decade between major transformations, the community moved toward a cadence of roughly three years between new standards.

C++17: enriching the language and its library

C++17 continued this modernization.

Important additions included:

  • std::optional;
  • std::variant;
  • std::any;
  • std::string_view;
  • structured bindings;
  • if constexpr;
  • significant improvements to the standard library.

These features made it possible to express more directly situations that previously required conventions or external libraries.

std::optional, for example, makes it possible to explicitly represent a value that may be absent.

The type itself documents that possibility.

This approach illustrates a trend in modern C++: using the type system to make program intentions more explicit.

C++20: concepts, ranges, and coroutines

C++20 represented another major step.

Three families of features attracted particular attention:

  • concepts;
  • ranges;
  • coroutines.

Concepts make it possible to express more clearly the constraints imposed on template parameters.

This is an important development for generic programming.

For many years, an error in the use of a template could produce extremely complex diagnostics.

Concepts make it possible to state more explicitly what a type must be able to do in order to be accepted.

Ranges provide a more expressive way to compose operations on sequences.

Coroutines, meanwhile, provide language mechanisms for suspending and resuming the execution of a function, which are useful for certain asynchronous models.

C++20 also introduced modules into the standard, with the ambition of providing a modern alternative to some historical uses of header files.

C++23 and continuous evolution

C++23 continued this cycle of improvement.

As is often the case with C++, evolution does not consist of abruptly replacing the existing language.

New features are added while the enormous historical codebase continues to matter.

The standard library grows.

Generic-programming mechanisms continue to evolve.

The use of constexpr allows more and more computation to take place at compile time.

Tools, compilers, and static analyzers are improving as well.

This incremental evolution is both a strength and a difficulty.

C++ can continue to modernize programming practices.

But it must carry an extremely long history with it.

Why not simply remove old features?

The question seems natural.

If some constructs are now discouraged, why not remove them?

Because one of C++’s greatest strengths is its enormous existing ecosystem.

Companies use millions of lines of code developed over decades.

Libraries and critical systems must continue to be maintained.

Abruptly removing a feature can break a considerable amount of software.

Compatibility is therefore a major constraint in the evolution of the language.

This policy contributes to its longevity.

But it also explains part of its complexity: several generations of programming practices can coexist within the same language.

Is C++ really compatible with C?

The relationship between C and C++ is more subtle than a simple “yes.”

C++ was historically designed as an extension of C and retains strong syntactic and conceptual similarities with it.

Many C programs can be adapted easily.

The two languages also share conventions and can interact through appropriate interfaces.

But C and C++ are now two distinct languages, each with its own standard and evolution.

A valid C program is not necessarily a valid C++ program.

Conversely, recommended idioms in modern C++ often differ greatly from those used in C.

Understanding this distinction prevents us from reducing C++ to “C with a few extra features.”

A multi-paradigm language

C++ is sometimes described as an object-oriented language.

That description is incomplete.

The language supports several styles:

  • procedural programming;
  • object-oriented programming;
  • generic programming;
  • functional programming in certain constructs;
  • compile-time metaprogramming;
  • low-level systems programming.

A single program can combine several of these approaches.

This flexibility is one of C++’s major strengths.

It allows programmers to choose abstractions suited to different problems.

But it also means that there are often several reasonable ways to accomplish the same task.

Metaprogramming: when the compiler computes

Templates had an unexpected effect.

Developers discovered that they could be used to perform computations during compilation.

Template metaprogramming thus became a field in its own right.

Originally, some of these possibilities almost resembled an ingenious exploitation of the template system.

Over successive versions, C++ introduced more direct mechanisms, notably constexpr and later consteval.

The language can now execute an increasing amount of logic at compile time.

This can be used to verify properties, prepare data, or eliminate certain runtime costs.

Once again, we find the objective of abstraction without sacrificing performance.

Why is C++ still used?

Whenever a new systems language appears, the disappearance of C++ is sometimes predicted.

Yet it remains extremely widespread.

Several reasons explain this longevity.

Performance

C++ can produce highly efficient native code.

Programmers have significant control over allocations, data layout, copies, and resources.

Predictability

In many systems, the issue is not simply being fast on average.

It is also necessary to control when certain expensive operations occur.

C++’s deterministic resource management is valuable in this context.

Ecosystem

Decades of development have produced an enormous number of libraries, engines, frameworks, and codebases.

Interoperability

C++ can interact closely with C and with many system APIs.

Compilers

GCC, Clang, and Microsoft Visual C++ are extremely mature and highly optimized tools.

Portability

C++ is available on a very wide range of platforms, from microcontrollers to powerful servers.

Video games and 3D engines

Video games are one of the most visible fields in which C++ remains dominant.

Game engines must manage:

  • graphics rendering;
  • physics;
  • audio;
  • artificial intelligence;
  • networking;
  • memory;
  • asset loading;
  • real-time constraints.

Performance and precise control over resources are essential.

Many major engines and games therefore make extensive use of C++.

This does not mean that every line of a game must be written in C++.

Scripting languages and higher-level tools are often used alongside it.

But C++ frequently remains at the core of the most demanding components.

Browsers and complex software

Modern browsers provide another example.

Displaying a web page involves rendering engines, JavaScript engines, networking, security, multimedia, graphics, and an enormous amount of logic.

Many browser components have historically been written in C++.

The language is also used in graphics-creation software, design tools, databases, and scientific applications.

Its natural territory often remains software that combines large scale with demanding performance requirements.

Embedded systems and hardware constraints

C++ is also widely used in embedded systems.

In these environments, memory may be limited.

Energy consumption may matter.

Hardware can impose precise constraints.

Some applications cannot depend on a heavy virtual machine or on a garbage collector whose pauses would be difficult to predict.

C++ makes it possible to use modern abstractions while retaining close control over hardware.

Of course, not every feature of the language is used in every embedded system.

Restricted subsets and strict development rules are common.

Finance, scientific computing, and infrastructure

In low-latency finance, a few microseconds can matter.

In scientific computing, large amounts of data must be processed efficiently.

In some infrastructure systems, CPU and memory consumption at scale becomes an economic issue.

These constraints continue to create an important role for C++.

The language makes it possible to build sophisticated abstractions while retaining access to the details that become important when performance reaches its limits.

The cost of this power: complexity

The longevity of C++ has a downside.

The language is vast.

It contains features inherited from different eras.

Some constructs interact in subtle ways.

Rules involving lifetimes, overload resolution, templates, or conversions can become complex.

A beginner can quickly write a small C++ program.

Truly mastering the language takes much longer.

This difficulty is not merely an accidental flaw.

It partly results from the conflicting goals pursued by C++:

  • remain efficient;
  • remain compatible;
  • provide powerful abstractions;
  • run on many platforms;
  • support several programming styles;
  • evolve without breaking existing software.

Memory safety becomes a major issue

A significant proportion of vulnerabilities in systems software has historically resulted from memory-management errors.

C++ makes it possible to write safe and well-structured code, notably through RAII, standard containers, and modern practices.

But it still allows dangerous low-level operations when programmers request them.

That capability is useful in some fields.

It is also a risk.

Contemporary discussions around so-called memory-safe languages have therefore renewed debate about the role of C++.

Newer languages seek to provide comparable systems performance while preventing more memory errors at compile time.

This competition is also pushing the C++ ecosystem to improve its tools, guidelines, and safety mechanisms.

C++ compared with newer languages

C++ has seen several generations of competitors appear.

Java offered portability and automated memory management.

C# developed a modern environment around .NET.

Go emphasized simplicity and concurrency.

Rust seeks to combine systems performance with strong memory-safety guarantees.

Other languages continue to explore new approaches.

Yet replacing C++ is not merely a matter of designing nicer syntax.

It is also necessary to consider:

  • existing codebases;
  • libraries;
  • tools;
  • available expertise;
  • supported platforms;
  • migration constraints;
  • interoperability with systems already in production.

This is why language evolution generally happens through coexistence far more than through instant replacement.

Why has C++ not been completely redesigned?

A new language could be simpler if it abandoned all compatibility.

But it would no longer be C++.

The C++ project has historically been based on continuous evolution.

This continuity allows old code to survive and gigantic systems to migrate gradually.

The price is accumulated complexity.

C++ therefore lives with a structural contradiction:

to remain modern, it must evolve; to preserve its industrial value, it cannot forget its past too quickly.

A large part of the standardization committee’s work consists precisely of managing this tension.

The role of the ISO committee

Since standardization, C++ has no longer been the project of a single person.

Bjarne Stroustrup remains a major figure in its history and continues to take part in discussions, but the language now evolves collectively.

Representatives from companies, research institutions, compiler vendors, and the wider community propose and evaluate changes.

Decisions must take many factors into account:

  • usefulness;
  • performance;
  • compatibility;
  • implementability;
  • consistency with the rest of the language;
  • developer experience.

This governance sometimes explains why certain changes take time.

But it is also necessary for a language used in critical systems around the world.

C++ is no longer the language of 1985

Comparing today’s C++ with its first version reveals a considerable transformation.

The language of 1985 was strongly focused on adding object-oriented mechanisms to C.

Modern C++ includes:

  • an extensive standard library;
  • generic containers;
  • algorithms;
  • lambdas;
  • automatic resource-management tools;
  • standardized concurrency;
  • compile-time computation mechanisms;
  • concepts;
  • ranges;
  • coroutines;
  • modules;
  • an extremely powerful template system.

Yet one guiding principle remains recognizable:

provide useful abstractions without taking away the programmer’s ability to control their cost.

C++ and the idea of a “general-purpose language”

C++ is not only a systems language.

It has been used to build almost every kind of software.

But it does not necessarily aim to be the simplest language for every task.

For a small script, Python may be faster to write.

For some web applications, other ecosystems are more natural.

For certain new systems projects, Rust may provide valuable guarantees.

The strength of C++ lies elsewhere.

It offers a rare combination of:

  • performance;
  • control;
  • abstraction;
  • portability;
  • maturity;
  • compatibility with an enormous body of existing software.

That combination explains its persistence.

A language shaped by its constraints

The history of C++ is sometimes told as an accumulation of features.

That interpretation misses the essential point.

Many of its characteristics can be explained by the constraints the language tries to satisfy simultaneously.

It wants richer abstractions than C.

It wants to remain usable for programs where performance matters.

It wants to operate without imposing a heavy runtime environment.

It wants to preserve strong compatibility with decades of code.

It wants to evolve with modern programming practices.

These goals are not always compatible.

The complexity of C++ is partly the result of this permanent negotiation.

From C with Classes to modern C++

The distance traveled since 1979 is considerable.

At first, Stroustrup mainly wanted to add mechanisms inspired by Simula to C.

Then came virtual functions, overloading, and inheritance.

Templates brought generic programming to the forefront.

The STL transformed the standard library.

C++98 stabilized the language internationally.

C++11 profoundly renewed programming practices.

C++14, C++17, C++20, and C++23 established a regular rhythm of evolution.

The language changes, but it never completely breaks with its history.

That may be its most remarkable characteristic.

Key takeaways

C++ was born in 1979 when Bjarne Stroustrup sought to combine Simula’s abstractions with the efficiency and ecosystem of the C language.

Initially called C with Classes, the project became C++ in 1983.

Its history, however, is not limited to object-oriented programming.

Templates and the STL made generic programming an essential pillar of the language.

The C++98 standard established an international specification, while C++11 opened the era of modern C++ with lambdas, move semantics, smart pointers, and many other improvements.

Later versions continued this modernization with concepts, ranges, coroutines, modules, and an increasingly rich standard library.

C++ remains important today because it combines properties that are difficult to bring together:

abstraction, performance, resource control, portability, and compatibility with several decades of software.

This power has a cost: the language is complex and retains historical mechanisms that modern practices often seek to avoid.

But that same continuity also explains its longevity.

More than forty years after C with Classes, C++ remains faithful to Stroustrup’s original problem: how can we build high-level software without unnecessarily losing control of the machine?

Frequently asked questions

Who created C++?

C++ was created by Bjarne Stroustrup at Bell Labs beginning in 1979.

What was C++ originally called?

The project was initially called C with Classes. It aimed to add mechanisms inspired especially by Simula to C, particularly classes.

Why is the language called C++?

In C, the ++ operator increments a value. The name C++ therefore suggests an “incremented C.” It was adopted in 1983.

Is C++ simply an object-oriented version of C?

No. Object orientation played an important role in its early history, but C++ is now a multi-paradigm language that also supports procedural programming, generic programming, metaprogramming, and other styles.

What is the difference between C and C++?

C and C++ are now two distinct languages. They share a history, much of their syntax, and many concepts, but each has its own standard and its own programming practices.

Why is C++11 so important?

C++11 profoundly modernized the language with features including lambdas, auto, move semantics, smart pointers, nullptr, constexpr, standardized concurrency, and many improvements to the type system.

Does C++ use garbage collection?

C++ generally does not rely on a mandatory garbage collector. It notably favors deterministic resource management through RAII, containers, and smart pointers.

Is C++ still used today?

Yes. It remains widely used in video games, 3D engines, browsers, embedded systems, scientific software, financial infrastructure, and many applications requiring high performance.

Why is C++ considered difficult?

Its long history, compatibility requirements, multiple paradigms, and the level of control it provides have produced a very large language. Modern C++ makes it possible to avoid many older practices, but mastering the language in depth remains demanding.

Will C++ be replaced?

New languages address some limitations of C++, particularly around memory safety and simplicity. But its enormous ecosystem, performance, portability, and existing codebases make a complete replacement unlikely in the short term. Evolution is more likely to happen through coexistence and gradual migration.

Sources and references

  1. 1.Bjarne Stroustrup --- A History of C++
  2. 2.Bjarne Stroustrup --- The Design and Evolution of C++
  3. 3.ISO C++ Foundation --- The Standard

Collection

Programming languages

  1. 01Grace Hopper: from early compilers to COBOL
  2. 02John Backus: FORTRAN, BNF, and the rejection of machine code
  3. 03Dennis Ritchie: the C language at the heart of Unix
  4. 04FORTRAN: proving that a compiler could compete with assembly
  5. 05The C language: making systems portable without hiding the machine
  6. 06Niklaus Wirth: from Pascal to Oberon, designing through simplicity
  7. 07Bjarne Stroustrup: designing C++ without giving up performance
  8. 08Pascal: learning to program by making structure visible
  9. 09C++: from C with Classes to a general-purpose language
  10. 10Object-oriented programming: objects, messages, and reusable abstractions
  11. 11Guido van Rossum: creating Python to make code readable
  12. 12Brendan Eich: JavaScript, from Netscape prototype to Web standard
  13. 13James Gosling: the engineer behind Java
  14. 14Python: readability, batteries included, and a global ecosystem
  15. 15Java: write once, run anywhere
  16. 16JavaScript: the language that made the Web interactive
  17. 17Ken Thompson: from Unix to Go, simplicity as a method
  18. 18John McCarthy: Lisp and the idea of programming with symbols
  19. 19Alan Kay: Smalltalk and the computer as a personal medium
  20. 20Barbara Liskov: the abstraction that made software modular
  21. 21Robin Milner: ML, machine-assisted proof, and languages of interaction
  22. 22Brian Kernighan: AWK, Unix, and the art of explaining code
  23. 23Anders Hejlsberg: from Turbo Pascal to C# and TypeScript
  24. 24Larry Wall: Perl, the language that connected the tools of the Internet
  25. 25Yukihiro Matsumoto: Ruby and programmer happiness
  26. 26Rasmus Lerdorf: PHP and the democratization of the dynamic Web
BiographyComputing historyBeginner

James Gosling: the engineer behind Java

How James Gosling and Sun's Green team designed Java: from Oak and virtual machines to portability and the language's lasting legacy.

17 August 20266 minRead

Was this article useful?