Skip to content

CT 301 Exam 1 Study Guide

CT 301: C++ Fundamentals · Summer 2026
Exam 1 Study Guide
Exam date: June 10, 2026. Scope: Lectures 1, 2, 3, 5, 6 + HW#1 topics.

This guide consolidates what you need to know for Exam 1 (June 10, 2026). Scope: Lectures 1, 2, 3, 5, 6, and HW#1 topics. Each section lists the core concepts, common pitfalls, and where to read for more.

For pointers, references, smart pointers, and ownership, this guide gives you the essentials and refers you to the separate Pointers Guide for the depth treatment.

0. How to use this guide

Work through the sections in order. For each section: skim, work the examples in your head (or on paper), then check the readings if anything is fuzzy. After you have studied, try the Practice Problems document to gauge your understanding. Do not flip to the practice problems first; you will memorize answers instead of learning concepts, and the exam questions will be different anyway.

1. Lecture 1: Hello World, Objects, Types, Values

What a C++ program looks like at the smallest scale.

Core concepts

Program structure. A C++ program is a set of translation units linked together. Each one is compiled separately; the linker glues them. Execution starts at main.

#include <iostream>

int main() {
    std::cout << "Hello, world!\n";
    return 0;
}

Fundamental types. Built-in types include int, double, char, bool, plus their sized variants (int32_t, int64_t, etc.). void means "no value." String literals are const char*; for actual text manipulation you use std::string.

Initialization. Modern C++ prefers brace initialization (also called uniform or list initialization):

int    a {42};      // brace init
double pi {3.14};
std::string name {"alice"};

The advantage: brace init catches narrowing conversions (int x {3.7}; is an error, while int x = 3.7; silently truncates).

auto. Lets the compiler deduce the type from the initializer. Useful when the type is long or obvious.

auto i = 42;                       // int
auto pi = 3.14;                    // double
auto v = std::vector<int>{1,2,3};  // std::vector<int>

auto does not let you skip initialization. auto x; is an error.

Objects, values, types. An object is a region of memory with a type. A value is what is stored. A variable is a named object. The same value (42) can be stored as different types (int, double, long), and each type has different rules.

Common pitfalls

See: Tour §1.1-1.6, §1.8. PPP Ch. 1-2 (+ §3.3-3.4). learncpp Ch. 1, learncpp Ch. 4 (Fundamental Data Types), learncpp 10.8 (auto).

2. Lecture 2: Functions, Scope, Constants, Pointers/References

The shape of a function, how variables come and go, what const and constexpr mean, and the basics of pointers and references.

Core concepts

Function basics. A function has a return type, a name, parameters, and a body.

int add(int a, int b) {
    return a + b;
}

Functions can be declared without being defined (forward declaration), as long as a definition appears somewhere before link time:

int add(int, int);          // declaration: tells the compiler "this exists"
// ...
int add(int a, int b) {     // definition: provides the body
    return a + b;
}

Scope. A name introduced in a block is visible only inside that block. Block scope, function scope, namespace scope, class scope, and global scope all exist.

int g = 0;                 // global / namespace scope
void f() {
    int x = 1;             // function scope
    if (x > 0) {
        int y = 2;         // block scope
        // x and y both visible here
    }
    // x visible; y is gone
}

const. Promises the compiler this value will not be modified through this name. The most common use:

const int max_size = 100;
void print(const std::string& s);   // s cannot be modified through this reference

constexpr. A stronger promise: the value must be computable at compile time.

constexpr int days_per_week = 7;
constexpr int square(int n) { return n*n; }
constexpr int x = square(5);   // computed at compile time

Use const for "I will not change this." Use constexpr for "this must be a compile-time constant."

Pointers and references (introduction). A reference is a nickname for an existing variable. A pointer is a variable holding an address. See the Pointers Guide for the full treatment, including ownership rules.

int x = 42;
int& r = x;            // r is another name for x
int* p = &x;           // p holds the address of x

Common pitfalls

See: Tour §1.3, §1.5-1.9 (pointers/refs in §1.7). PPP Ch. 3 & 7 (pointers/refs in Ch. 15-16). learncpp Ch. 5 (const/constexpr), learncpp Ch. 7 (Scope & Namespaces), learncpp Ch. 12 (References & Pointers). For more depth on pointers/refs, see the Pointers Guide.

3. Lecture 3: User-Defined Types and Modularity

Building your own types: enums, structs, classes. Splitting programs across files.

Core concepts

Enumerations. enum class is the modern, strongly-typed enum. Values are scoped (you write Color::Red, not just Red) and they do not implicitly convert to integers.

enum class Color { Red, Green, Blue };
Color c = Color::Red;
// int n = c;        // error: no implicit conversion
int n = static_cast<int>(c);   // ok: explicit cast

Plain enum (no class) leaks names into the surrounding scope and converts to int implicitly; avoid it in new code.

Structs and classes. Both define a user type with data members and member functions. The only language difference: struct defaults to public, class defaults to private.

struct Point {
    int x = 0;
    int y = 0;
};

class Date {
    int y_, m_, d_;
public:
    Date(int y, int m, int d);
    int year() const { return y_; }
};

Convention: use struct for plain data with no invariants; use class when there is an invariant to maintain.

Namespaces. A way to group related names and avoid collisions.

namespace inv {
    class Inventory { /* ... */ };
}
inv::Inventory my_inv;   // qualified name

Inside a .cpp file you can write using namespace inv; for shorthand. Do not put using namespace ...; in a header file; it pollutes every file that includes it.

Header files and separate compilation. A header (.h) declares names; a source file (.cpp) defines them. Including a header is essentially copy-pasting its contents into the including file. Header guards (#pragma once or include guards) prevent multiple inclusion in one translation unit.

// item.h
#pragma once
#include <string>
namespace inv {
    class Item {
    public:
        virtual std::string id() const = 0;
        virtual ~Item() = default;
    };
}
// item.cpp
#include "item.h"
// definitions of non-inline member functions go here

Common pitfalls

See: Tour Ch. 2 (UDTs) + Ch. 3 (Modularity). PPP Ch. 8 + Ch. 7. learncpp Ch. 13 (Enums & Structs), learncpp Ch. 14 (Introduction to Classes), learncpp 7.2 (Namespaces).

4. Lecture 5: Functions in depth (declarations, definitions, scope, namespaces, headers)

A deeper look at functions: how to split declaration from definition, how the linker finds things, and how to pass arguments efficiently.

Core concepts

Declaration vs definition. A declaration introduces a name. A definition provides the body or storage. You can declare a function many times but define it exactly once (ODR: One Definition Rule).

// declaration (typically in a header)
double area(double r);

// definition (in a .cpp file)
double area(double r) { return 3.14159 * r * r; }

Headers and separate compilation. The header area.h is included anywhere the declaration is needed. The definition lives once in area.cpp. The linker matches calls to the one definition.

Argument passing. Three common modes:

void by_value(std::string s);            // copies (or moves) the argument
void by_const_ref(const std::string& s); // no copy; cannot modify
void by_ref(std::string& s);             // no copy; may modify (caller's value)

Guideline:

Return values. Prefer return by value (NRVO + implicit move on return makes this cheap for containers). Return by reference only when the referent outlives the call (a parameter, a member of *this, a static). Do not return references to locals. See the Pointers Guide §5 for the full discussion.

Default arguments. Specified in the declaration, not the definition:

void f(int x, int y = 0);   // y defaults to 0 if omitted

Function overloading. Two functions can share a name if their parameter lists differ. The compiler picks based on argument types.

int abs(int x);
double abs(double x);     // ok: different parameter types

Return type alone is not enough to overload.

Namespaces in function scope. A using declaration in a function brings one name in for that scope. A using directive (using namespace X;) brings everything; safer inside a function than a header.

Common pitfalls

See: Tour §1.3, §1.5, §3.2-3.4. PPP Ch. 7. learncpp 2.1 (Introduction to functions), learncpp 2.11 (Header files), learncpp 12.6 (Pass by const reference).

5. Lecture 6: Classes and class design (interface, operators, inheritance)

Designing user types with proper interfaces, operator overloading, and inheritance hierarchies.

Core concepts

Concrete classes. Classes whose representation is part of the type. They have an invariant maintained by the constructor and member functions, and they are usually copyable.

class Date {
    int y_, m_, d_;
public:
    Date(int y, int m, int d) : y_{y}, m_{m}, d_{d} {}
    int year() const { return y_; }
    int month() const { return m_; }
    int day() const { return d_; }
};

Note the constructor initializer list (: y_{y}, m_{m}, d_{d}) and const member functions (do not modify the object).

Access control. public for the interface; private for representation. Members default to private in class, public in struct.

Abstract classes. A class with at least one pure virtual function. Cannot be instantiated; only derived classes can be created.

class Item {
public:
    virtual std::string id() const = 0;   // pure virtual
    virtual double currentValue() const = 0;
    virtual ~Item() = default;            // virtual destructor: essential
};

Virtual functions and dynamic dispatch. A non-static member function declared virtual is dispatched at runtime based on the actual type of the object, not the type of the pointer or reference.

class Item { /* virtual methods */ };
class Equipment : public Item { /* overrides */ };

std::unique_ptr<Item> p = std::make_unique<Equipment>(...);
p->currentValue();   // calls Equipment::currentValue at runtime

Mark overrides with override (compiler checks that the signature actually overrides something):

class Equipment : public Item {
public:
    std::string id() const override;
    double currentValue() const override;
};

Virtual destructor. Required for any class meant to be used through a base-class pointer. Otherwise delete base_ptr only runs the base destructor, leaking the derived part.

class Item {
public:
    virtual ~Item() = default;   // critical
};

Inheritance. class Equipment : public Item means "Equipment IS-A Item." Public inheritance models the IS-A relationship. Inside the derived class, you can call base class methods and (for protected/public members) access base members.

Operator overloading. Some operators can be overloaded to make user types behave like built-in types.

class Date {
    // ...
public:
    bool operator==(const Date& other) const {
        return y_ == other.y_ && m_ == other.m_ && d_ == other.d_;
    }
};

Common overloads: ==, !=, <, << (for stream output), +, +=. Do not overload &&, ||, or , (their semantics change unexpectedly). Many operators can be member functions; some (like << for output) must be free functions.

Object slicing. Assigning a derived object to a base object by value drops the derived part:

Equipment e{...};
Item it = e;     // SLICING: it is a base-only copy; virtual dispatch lost

Always pass and store polymorphic types by reference, pointer, or smart pointer to avoid slicing.

Common pitfalls

See: Tour Ch. 5 (Classes), §5.2 (concrete), §5.3 (abstract), §5.4 (virtual), §5.5 (hierarchies); Ch. 6 (operator overloading). PPP Ch. 8 + Ch. 12. learncpp Ch. 14 (Classes), learncpp Ch. 21 (Operator Overloading), learncpp Ch. 24 (Inheritance), learncpp 25.2 (Virtual Functions).

6. HW#1 topics (cross-reference)

HW#1 exercised the material from Lectures 1, 2, 3, 5, and 6 in a single project: an inventory system with an Item hierarchy, four states, and an Inventory class that owns items via std::unique_ptr.

The HW#1-specific topics that are likely to appear on the exam:

Common exam pitfalls (HW#1)

See: Tour Ch. 5, Ch. 6, §15.2. PPP Ch. 8, Ch. 12. [learncpp Ch. 14, 22, 24, 25.2]. Full treatment in the Pointers Guide for ownership-related questions.

How the exam is structured (procedural)

What to do the night before