TIC Chapter 1: Introduction to Objects

Source: Thinking in C++, Vol. 1, Preface + Chapter 1 (pp. 1–82)

Preface: Why OOP, Why C++

OOP is a fundamental shift in thinking, not just a new syntax. Three reasons C++ is the vehicle:

  1. Existing investment: most programmers know C; C++ adds OOP without abandoning that knowledge
  2. Efficiency: C++ runs within ~10% of equivalent C code
  3. Ubiquity: largest existing C++ codebase of any OOP language

Five stages of learning C++: (1) introductory survey, (2) basic types and functions, (3) classes, (4) reuse (inheritance + composition), (5) templates + advanced.

The Progress of Abstraction

All programming languages provide abstractions. The expressiveness of an abstraction determines the complexity of problem you can solve.

LevelLanguagesModel
MachineAssemblyMachine operations directly
ProceduralC, Fortran, BASICFunctions; solution space
OOPC++, Java, SmalltalkObjects; problem space

Procedural programs force you to build an intermediate mental model to map problem to machine. OOP lets you model the problem directly.

Alan Kay’s 5 Characteristics (Smalltalk)

Alan Kay, principal designer of Smalltalk, identified five characteristics of OOP:

  1. Everything is an object — an object stores data and can receive requests
  2. Objects communicate by sending messages — a message is a request to call a function
  3. Each object has its own memory made of other objects — composition is fundamental
  4. Every object has a type (class) — an object is an instance of its class
  5. All objects of a particular type can receive the same messages — substitutability (a Circle is a Shape and responds to draw())

Eckel’s summary: “An object has state, behavior, and identity.”

The Object Interface

An interface is the set of requests you can make of an object. The class defines the interface. UML represents a class as a box: type name on top, member functions below.

The key question for any object: what messages can you send it?

Hidden Implementation (Encapsulation)

Access specifiers control visibility:

  • public — available to anyone
  • private — class internals only (not even derived classes)
  • protected — class + derived classes

Two roles:

  • Class creator: designs the type; hides implementation
  • Client programmer: uses the type without needing to know internals

This separation enables changing internals without breaking clients.

Reusing the Implementation: Composition (“Has-a”)

A new type contains objects of existing types as members. A Car has-a Engine. Often called aggregation for looser relationships.

Composition is more flexible than inheritance: you can swap the composed object at runtime. Prefer composition over inheritance as a default rule.

Inheritance (“Is-a” and “Is-like-a”)

A derived class inherits the interface (and usually implementation) of a base class.

  • Overriding: derived replaces a base function with its own version
  • “Is-a” (pure substitution): derived adds no new interface members — completely substitutable
  • “Is-like-a” (extension): derived adds new members — true substitution becomes harder

The Liskov Substitution Principle: you should be able to use a derived object anywhere a base object is expected.

Polymorphism

                    Shape
                   /  |  \
              Circle  Square  Triangle

If you call draw() on a Shape pointer that actually points to a Circle, which draw() runs?

MechanismTimeNotes
Early binding (C default)Compile timeFixed address; fast; wrong for polymorphism
Late binding (OOP)RuntimeAddress looked up via vtable; virtual keyword

The virtual keyword tells the compiler to use late binding for this function. Upcasting = treating a derived object as its base type; it’s safe and automatic.

Polymorphism enables extensibility: write code against the base class once; new derived types work automatically.

Creating and Destroying Objects

LocationLifetimeCost
Stack (scoped variable)Until block exitsFast; automatic cleanup
Heap (new / delete)Until programmer frees itFlexible; leaks if forgotten

C++ has no garbage collector. Modern C++ uses RAII and smart pointers (unique_ptr, shared_ptr) to manage heap objects, but Vol. 1 teaches the fundamentals first.

Exception Handling

An exception is thrown at the error site; execution jumps to a handler (catch block). All code between throw and catch is bypassed. Guarantees: errors are either handled or propagated; no silent failures like unchecked C error codes.

Analysis & Design Methodology

Eckel’s 6-phase process:

PhaseNameKey Activity
0PlanWrite a one-paragraph mission statement
1What are we making?Use cases + CRC cards
2How will we build it?Class diagrams, UML, interfaces
3Build the coreImplement essential structure first
4Iterate the use cases1–3 week cycles; test + refine
5Evolution”Maintenance” — ongoing changes

CRC cards: Class-Responsibility-Collaboration on 3×5 index cards — low-tech but highly effective for early design.
Use cases: user-perspective scenarios describing what the system does.
XP (Extreme Programming): write tests first (clarifies interface, provides safety net); pair programming.

Five Stages of Object Design

  1. Object discovery (from problem description)
  2. Object assembly (what does this object need to know?)
  3. System construction (how do objects collaborate?)
  4. System extension (adding capabilities)
  5. Object reuse (generalizing for other contexts)

Object Design Guidelines

  • Let problems generate classes — don’t force OOP upfront
  • Discovering interfaces is most of the design work
  • Start programming early; let the system evolve
  • Keep it simple: three similar lines beats a premature abstraction

Why C++ Succeeds

  • Better C: type checking, references, function overloading, default args, namespaces
  • Efficiency: within ~10% of C; design decisions favor high-speed production programming
  • Expressibility: problem-space modeling, operator overloading
  • Library leverage: reuse pre-built class libraries
  • Templates: “a class of anything” — source-code reuse
  • Exception handling: guaranteed error handling
  • Gradual transition: don’t rewrite existing C code; migrate incrementally

Strategies for Transitioning to C++/OOP

  1. Get training / mentoring (avoid “common design errors” from inexperienced use)
  2. Start with a low-risk project
  3. Model from success — study well-designed C++ codebases
  4. Use existing class libraries
  5. Don’t rewrite existing C code unless it’s already causing problems
  6. Manage management: OOP benefits take 3–6 months to materialize

Common Design Errors

When teams start OOP without expert guidance, they frequently go off on bad tangents that would be obvious to an experienced practitioner. C++‘s backward compatibility with C creates “dark corners” — subtle bugs and gotchas that don’t exist in cleaner OOP languages. Expert mentoring or outside consultants prevent much of this trauma.

Summary

OOP is about narrowing the gap between the problem space and the solution space. The five OOP characteristics, the UML interface model, and the design methodology all serve this goal. C++ achieves it while preserving C’s efficiency and existing code investments.