C++: From C with Classes to an International Standard
Trace C++ from Bell Labs' C with Classes through Cfront, the 1985 book, committee work, and ISO standardization without treating it as C's superset.
C++ did not begin as a committee-designed language or as a plan to replace C. It began with Bjarne Stroustrup’s effort at Bell Labs to bring facilities for organizing large programs into a language suitable for systems work. The early language was called C with Classes. Its history tracks an attempt to combine ideas from Simula with C’s efficiency, flexibility, and existing ecosystem, followed by a long process of implementation, user feedback, and standardization.
That origin story helps explain why C++ accumulated multiple programming styles. It was not designed around one pure model. Its classes, inheritance, generic programming, low-level control, and compatibility goals came from different needs and developed at different times. A historical account should therefore resist describing C++ as simply “C with object-oriented syntax” or as a strict superset of C. The language evolved through versions, and the standard does not define every valid C program as valid C++.
A systems programmer’s problem at Bell Labs
Stroustrup began work on C with Classes around 1979 at AT&T Bell Laboratories. His published history explains that he wanted the organization facilities of Simula while retaining C’s efficiency and flexibility for systems programming. He had encountered Simula while working on distributed systems and wanted abstractions that could help structure software without giving up practical control of implementation.
The goal was not merely to add a class keyword. Programs with growing complexity needed ways to represent concepts, control invariants, and organize interfaces. A class could group state and operations; derived classes could express relationships; stronger typing could detect some mistakes; and inlining or default arguments could make abstractions more practical in code that needed performance and convenience.
C was a compelling base because it was already widely used for systems software and exposed low-level facilities. But C’s structure did not provide the same built-in mechanisms for user-defined types and larger program organization. C with Classes tried to extend the language while keeping its implementation and programming environment close enough to existing C practices to be useful.
Cfront made the language implementable
An important part of C++’s early history is Cfront, the compiler developed to translate C++ source into C. This approach let the new language reuse existing C compilers and toolchains on many machines. The translation model allowed the language to reach a broader range of hardware than a completely new native code generator might initially support.
Cfront was not simply a text macro expander. Stroustrup’s retrospective describes a real compiler with parsing, symbol tables, and an internal representation for classes and functions. It had to translate language abstractions into mechanisms that C compilers and linkers could handle. Names, object layout, function calls, and runtime support all required decisions.
The choice had tradeoffs. Reusing C compilers made portability and bootstrapping practical, but the implementation had to encode C++ semantics in generated C. Debugging generated output could be difficult, and the behavior of C++ programs depended on both the front end and the target C compiler. As C++ matured, native code-generating implementations became common, but Cfront remains an important artifact of the language’s early diffusion.
The name changed as the design grew
The language’s name evolved from C with Classes to C++. Stroustrup’s historical paper describes the period in which the language gained additional facilities and a broader user community; the name C++ is credited to Rick Mascitti. The notation borrowed C’s increment operator to suggest an evolution from C, not a claim that the new language was a standards-compatible superset.
The earliest descriptions and releases should not be collapsed into one date. Work began in 1979, the C with Classes description appeared in the early 1980s, and C++ became the name in 1983. Cfront and the first edition of The C++ Programming Language became public in 1985. The first commercial implementation also appeared in 1985 according to the Standard C++ FAQ. The exact timeline should be drawn from the author’s history and historical artifacts, not from the first year in which any one feature was tested.
The first edition of The C++ Programming Language was more than a popular book. Before an international standard existed, it documented a language that compilers and users were still learning. As implementations and user demand grew, the book could not remain the language’s sole specification. Vendors added features, and different compilers risked implementing different dialects.
Design goals created deliberate tensions
C++ aimed to support abstraction without making low-level programming impossible. A class could encapsulate a representation, but systems developers still needed control over memory, layout, and execution cost. A high-level facility would be more attractive if it could compile into code comparable to a hand-written C implementation where the abstraction did not require extra runtime work.
This ambition shaped the design principle often summarized as zero-overhead abstraction. It should be interpreted as a design goal, not a guarantee that every C++ feature has zero cost or that all compiler outputs are identical. Dynamic dispatch, allocation, exception handling, and runtime library choices have costs. The principle expresses a preference: features should not impose mandatory overhead when unused, and abstractions should be implementable efficiently.
Another tension came from compatibility. C++ wanted access to the C ecosystem and low-level techniques, but as it evolved it gained semantics that differed from C. The result was a language that could interoperate with C through defined interfaces and conventions, but was not simply a source-level superset. Names, types, declarations, and library rules differ. Treating the two as interchangeable leads to both historical and technical mistakes.
The language also changed substantially after the early C with Classes period. Multiple inheritance, templates, exceptions, namespaces, and other facilities were introduced across different stages. Some were developed in response to users building larger systems; others reflected research or committee proposals. No single designer or meeting created the complete modern language.
From one compiler to a standards process
As C++ was adopted by multiple vendors and organizations, common semantics became necessary. Compiler portability could not depend on every vendor independently interpreting books, papers, and user expectations. Industry participants formed a standards effort, first through U.S. and then international committee work. The ISO/IEC JTC 1/SC 22/WG 21 committee became the international working group for C++.
The committee process added a new kind of authorship. Stroustrup’s design history remained essential, but a language standard was the result of proposal, review, discussion, and agreement among many participants. Committee papers record how features and wording were considered; the standard itself captures the agreed contract for an edition. A feature’s presence in a current language does not mean it was part of the 1979 design.
The first edition of ISO/IEC 14882 was published in 1998. The initial standard stabilized a widely used language after years of evolution and vendor practice. It also created a basis for later revisions. The standardization process did not freeze C++; it established an agreed baseline against which future changes could be proposed and implementations evaluated.
Standardization changed how programmers could discuss conformance. Rather than asking whether a compiler matched a particular vendor manual or book edition, they could test its implementation against a specified language standard. This did not erase implementation-defined and undefined behaviors, nor did it make every program portable. It gave the ecosystem a shared reference point and a formal revision process.
A language with more than one lineage
C++ is often described through its object-oriented features, but its history also includes generic programming, systems programming, and a rich standard library. Templates provided compile-time parameterization and later became the foundation for generic algorithms and containers. The C++ standard library gave programmers reusable data structures and algorithms beyond the core language.
Simula’s influence on classes and program organization is real, but C++ was not a renamed Simula. C’s syntax, translation environment, performance expectations, and installed base shaped the resulting language. Stroustrup’s own history emphasizes the combination of ideas and constraints rather than a single parent language. The standardization process later incorporated contributions from a wide community.
This mixed lineage explains why language debates can talk past one another. One programmer may value direct hardware access; another may value static type checking; a third may use templates to express generic algorithms. C++ has room for all of these styles, but its complexity and multiple abstraction levels are part of the tradeoff. The history does not show a neat progression from “low-level” to “high-level”; it shows a continuing effort to make both coexist.
Researching old C++ claims
When a source claims that a feature existed in “C++” in a particular year, identify the language release, compiler, and specification being discussed. Early C with Classes was not identical to the 1985 commercial Cfront release, and neither was identical to ISO C++98. A sample program may compile on one implementation because of an extension without belonging to a published standard.
Use Stroustrup’s HOPL history for design chronology and rationale. It is a first-person technical history, valuable for intent and implementation choices, but it is retrospective and should be compared with contemporaneous manuals or archived compiler releases for exact behavior. Use the WG21 archive and standards page for committee and publication dates. A standards committee archive proves what work was recorded, not that every compiler adopted it immediately.
Finally distinguish the C and C++ standards. Their committees have coordinated work, but the languages have separate specifications. A C program that compiles as C++ may be a useful porting example, but it does not establish that C++ is a superset. Historical descriptions should be equally careful.
A standard born from practical compromise
C++ grew because programmers wanted stronger organization and abstraction while retaining access to the systems-programming world around C. Its history moved from one engineer’s work at Bell Labs through a compiler, books, commercial implementations, and a committee process. Each stage broadened participation and changed what counted as the language’s authoritative description.
The enduring lesson is that a language is not only a syntax or an author’s design. It is a relationship among goals, compilers, users, libraries, and standards. C++’s diverse feature set reflects the range of problems it set out to address and the compromises required to serve an existing ecosystem. Understanding that origin makes the language’s strengths and complexity easier to interpret without mistaking either for an accident.
Related:
- How C Became a Standard Language Instead of One Compiler’s Dialect
- Simula 67: When Simulation Concepts Became a General Programming Language
Sources: