TIC Chapter 2: Making & Using Objects
Source: Thinking in C++, Vol. 1, Chapter 2 (pp. 83–120)
Goal: enough C++ syntax and program construction concepts to write and run simple OOP programs. This chapter treats classes as black boxes — you use them without knowing how they’re built.
The Process of Language Translation
All computer languages translate source code into machine instructions. Two approaches:
Interpreters: translate and execute immediately (BASIC, traditional Python). Advantages: rapid iteration, specific error messages. Disadvantages: slow (re-translates repeated code), hard to build large programs.
Compilers: translate the entire program to machine code before execution. Advantages: fast executables, separate compilation for large programs. Disadvantage: slower code → run cycle.
C++ is compiled.
The Compilation Pipeline
Source.cpp → Preprocessor → Parser (parse tree) → [Global optimizer]
→ Code Generator → Object Module (.o/.obj)
→ [Peephole optimizer] → Linker → Executable
- Preprocessor: handles
#include, macros, conditional compilation - Parser: builds parse tree; performs static type checking (catches type mismatches at compile time)
- Code generator: produces object module (
.o/.obj— pre-OOP use of “object” = “chunk of code”) - Linker: combines object modules; resolves external references; adds startup module (initializes stack and variables)
Static type checking: C++ checks types at compile time, not runtime — maximizes speed, catches errors early.
Separate compilation: each file compiled independently; the linker assembles. The function is the atomic unit of code — cannot span files.
Linker Details
- Searches libraries by index — links only the needed object module, not the whole library
- “Secret additions”: a startup module is always silently linked to initialize the stack
- Standard library searched automatically; add-on libraries named explicitly
- Library search order matters — unresolved references searched left-to-right; a dependency must appear after its user in older linkers
Declarations vs. Definitions
The most important mechanical distinction in C and C++:
| Declaration | Definition | |
|---|---|---|
| Says | ”This exists somewhere" | "Make it here” |
| Allocates storage | No | Yes |
| Allowed count | Many | One (ODR) |
ODR = One-Definition Rule: a function or variable may be defined exactly once across all translation units.
Function Declarations (Prototypes)
int func1(int, int); // declaration (semicolon, no body)
int func1(int length, int width); // same — argument names optional, helpful
extern int func1(int length, int width); // extern is superfluous for functionsC++ gotcha: int func2() = “takes no arguments.” In C it meant “takes any arguments.” C++ is stricter.
Function Definitions
int func1(int length, int width) {
return length * width;
}Braces replace the semicolon. Argument names required if used in the body.
Variable Declarations
int a; // declaration AND definition (allocates storage)
extern int a; // declaration only (storage defined elsewhere)Header Files
A header file (filename.h or <header>) contains external declarations for a library:
#include <iostream> // angle brackets: search include path (system)
#include "local.h" // double quotes: search current dir firstStandard C++ format (no .h, templatized version):
#include <iostream> // NOT <iostream.h>
#include <string>
#include <fstream>
#include <vector>C library headers in C++ style:
#include <cstdlib> // was <stdlib.h>
#include <cstdio> // was <stdio.h>Don’t mix .h and non-.h forms for the same header.
Namespaces
C’s global namespace causes name collisions in large programs. C++ solution: namespace keyword.
All Standard C++ library names are in the std namespace:
using namespace std; // expose std names for this file (OK in .cpp)
// NEVER put this in a header fileOld #include <iostream.h> implied using namespace std; — that’s backward compatibility. The book uses modern <iostream> + explicit using namespace std;.
Your First C++ Program
//: C02:Hello.cpp
// Saying Hello with C++
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World! I am "
<< 8 << " Today!" << endl;
}cout= console output object;<<= “send to” (overloaded from bitwise left shift)- Arguments chained left to right;
endl= newline + buffer flush main()always returnsintin C++; return is optional at the end (compiler insertsreturn 0)- Free-form language: newlines ignored; semicolons end statements; a statement can span multiple lines
- Comments:
/* */(multi-line) and//(single-line, preferred)
More Iostreams Features
cout << dec << 15; // decimal (default)
cout << oct << 15; // octal output
cout << hex << 15; // hex output
cout << 3.14159; // float auto-formatted
cout << char(27); // cast int → char → sends ASCII 27 (escape)Manipulators (dec, oct, hex) change stream state — they don’t output, they affect subsequent output.
Character array concatenation (preprocessor feature):
cout << "Long string split "
"across lines.\n"; // preprocessor joins adjacent stringsReading Input
int number;
cin >> number; // reads from stdin; waits for matching typeIntroducing std::string
Character arrays ("quoted text") are fixed at compile time and require manual memory management. The string class handles everything:
#include <string>
string s1, s2; // empty
string s3 = "Hello, World."; // init from char array
string s4("I am"); // alternate syntax
s2 = "Today"; // assign (automatic cleanup of old content)
s1 = s3 + " " + s4; // concatenate
s1 += " 8"; // append
cout << s1 + s2 + "!" << endl; // send to cout directlyThe string class is in namespace std and requires using namespace std;. It grows automatically — no allocation needed.
Reading and Writing Files
#include <fstream> // also implicitly includes <iostream>
ifstream in("Scopy.cpp"); // open for reading (behaves like cin)
ofstream out("Scopy2.cpp"); // open for writing (behaves like cout)
string s;
while(getline(in, s)) // read one line; returns false at EOF
out << s << "\n"; // getline discards newline — must add backgetline() is the key idiom for line-by-line file processing. The while(getline(in, s)) pattern reads until EOF.
Entire file into a single string:
string entire, line;
while(getline(in, line))
entire += line + "\n";Introducing std::vector
When you don’t know how many objects you’ll need, use vector — a dynamically-sized sequence container.
#include <vector>
vector<string> v; // template: vector of strings
ifstream in("file.cpp");
string line;
while(getline(in, line))
v.push_back(line); // add to end
for(int i = 0; i < v.size(); i++)
cout << i << ": " << v[i] << endl; // indexed access, 0-basedvector is a template: vector<int>, vector<float>, vector<string> — all valid.
Key operations:
push_back(x)— append to endv[i]— index access (operator overloading; 0-based)v.size()— number of elementsv[i] = expr— assign to element
The for loop: for(init; test; increment). The canonical idiom: for(int i = 0; i < v.size(); i++). i++ = post-increment (add 1 to i after each iteration).
Word-by-word reading (splits on whitespace):
string word;
while(in >> word)
words.push_back(word);STL Note
vector traces to the Standard Template Library (Alex Stepanov, HP, 1994 Standards meeting in San Diego). The STL is now integrated into the Standard C++ Library with changes. This book avoids the term “STL” and says “Standard C++ Library containers” instead.
Chapter Summary
The ease of OOP comes from reusing well-designed library classes. When someone else has defined the objects, you just:
- Include the header file
- Create the objects
- Send messages to them
This chapter demonstrated this with three key Standard C++ Library tools:
- iostream family:
cout,cin,ifstream,ofstream,getline - string class: dynamic string handling with clean operator syntax
- vector template: dynamically-sized container for any type
The point of OOP: hide the details so you can “paint with a bigger brush.”
Some fundamental C aspects (arithmetic, control flow, pointers) can’t be avoided — they’re covered in Chapter 3.