Introduction to C++ Variables and Classes, CS 225 Lecture 01 – Study Notes
offline

Difficulty: Introductory | Prerequisites: Basic programming experience (ideally Java or similar)


Big Picture

This is the opening lecture for CS 225, a data structures course taught in C++. If you are coming from a Java background, this lecture bridges that gap by introducing C++ syntax for variables, classes, and file organisation. The concepts here, particularly encapsulation and the separation of interface from implementation, underpin every data structure you will build for the rest of the course. You need to be comfortable with these fundamentals before moving on to memory management, pointers, and more complex class design.


TL;DR

C++ variables are either primitive (int, char, double, etc.) or user-defined via classes. Classes bundle data and methods together, with the interface declared in a .h header file and the implementation written in a .cpp file. Inclusion guards (#pragma once or #ifndef) prevent a header from being compiled more than once.

Key Terms

Primitive type

A built-in data type provided by the language: int, char, double, bool, float, pointer. Think of these as the basic building blocks that C++ already knows how to handle without any extra code from you.

User-defined type (complex variable / object)

A data type you create yourself using a class. In simple terms, you are teaching C++ about a new kind of thing (like a Cube) that it did not know about before.

Class

A blueprint that bundles together variables (data) and methods (functions) into a single unit. Think of it as a container that holds everything related to one concept.

Encapsulation

The principle of separating what a class does (its interface) from how it does it (its implementation), while keeping both as a cohesive unit. In simple terms, the outside world only needs to know what buttons to press, not what happens inside the machine.

Interface (API)

The public-facing part of a class: the method signatures and public members that tell other code what the class can do. This lives in the .h header file.

Implementation

The actual code that carries out what the interface promises. This lives in the .cpp source file.

Header file (.h)

The file where you declare your class and its members (method signatures, member variables). It defines the class by listing its components. Think of it as the table of contents for your class.

Source file (.cpp)

The file where you write the actual method bodies and initialise variables. This is where the work gets done.

Inclusion guard

A mechanism that prevents a header file from being included more than once during compilation. Either #pragma once or the #ifndef / #define / #endif pattern. Without it, you risk duplicate definition errors.

Scope resolution operator (::)

The :: operator tells the compiler which class a method belongs to. Cube::getVolume() means "the getVolume method that belongs to the Cube class." Think of it as a surname for a function.

Defining vs. declaring

A class is defined by specifying its members (what it contains). Individual methods and variables are declared by specifying their components (return type, name, parameters). In simple terms, defining says "this class exists and has these parts," while declaring says "this method exists and looks like this."


Core Content

C++ Variable Types

  • Every variable in C++ has a type, which is either primitive or user-defined.

  • Primitive types are the ones the language provides out of the box: int, char, double, bool, float, and pointer. These work much the same as in Java.

  • User-defined types are created through classes. When the built-in types are not enough to model what you need (a Cube, a LinkedList, a Student), you write a class to define a new type.

Encapsulation and the Interface/Implementation Split

  • Encapsulation is about separating the interface (what a class can do) from the implementation (how it does it), while bundling them together as one unit.

  • The interface is the API: the set of public method signatures. It answers the question, "What can I ask this class to do?"

  • The implementation is the method bodies: the actual logic. It answers, "How does this class do it?"

  • The key benefit: you can change the implementation without breaking any code that uses the interface. As long as getVolume() still returns a double, the caller does not care whether you calculated it with length_ * length_ * length_ or some other formula.

The .h and .cpp File Convention

  • In C++, convention splits each class across two files:

    • cube.h (the header file): contains the class definition, which lists all its members (method declarations, member variables). This is the interface/API.

    • cube.cpp (the source file): contains the method implementations. This #includes the corresponding .h file.

  • A class is defined in the .h file by specifying its members.

  • Individual methods and variables are declared in the .h file by specifying their return type, name, and parameters.

  • The method bodies are implemented in the .cpp file.

Example:

// cube.h
#pragma once
class Cube {
  public:
    double getVolume();
  private:
    double length_;
};
// cube.cpp
#include "Cube.h"
double Cube::getVolume() {
  return length_ * length_ * length_;
}

Inclusion Guards

  • Header files can be #included by multiple other files. Without protection, the same header could be compiled more than once in a single build, causing duplicate definition errors.

  • Two equivalent approaches:

    • #pragma once: a single directive at the top of the header. Cleaner and increasingly preferred.

    • #ifndef / #define / #endif: the traditional pattern. You define a unique macro name (e.g. CUBE_H_) and wrap the entire header in it.

  • Both achieve the same result. Pick one and stay consistent across your project.

Scope Resolution Operator (::)

  • In the .cpp file, you use :: to tell the compiler which class a method belongs to.

  • Cube::getVolume() means "the getVolume() method of the Cube class."

  • This is necessary because multiple classes could each have a method called getVolume(), and the compiler needs to know which one you are implementing.


Common Misconceptions

  • "Defining" and "declaring" mean the same thing. They do not. A class is defined by listing its members. A method or variable is declared by specifying its signature (return type, name, parameters). The distinction matters when the compiler tells you something is "undefined" or "redeclared."

  • The .h file contains the implementation. The .h file contains only the interface (declarations). The implementation (method bodies) goes in the .cpp file. Putting implementation in the header can cause linker errors in multi-file projects.

  • You do not need inclusion guards if you only include a header once. In practice, headers include other headers, creating chains. A header you think you include once may end up included several times through different paths. Always use a guard.

  • #pragma once and #ifndef guards behave differently. For nearly all purposes they are equivalent. #pragma once is not technically part of the C++ standard, but it is supported by every major compiler and is simpler to write.


Why It Matters / Exam Flags

  • ⚠️ Know the difference between defining a class and declaring a method. Exam questions love to test this distinction.

  • ⚠️ Be able to split a simple class across a .h and .cpp file from scratch. This is a foundational skill tested throughout the course.

  • ⚠️ Understand what encapsulation buys you: the ability to change implementation without breaking the interface. This concept recurs in every data structure.

  • ⚠️ Know what the scope resolution operator :: does and why it is needed in .cpp files.


Quick Self-Test

  1. True or false: bool is a user-defined type in C++.

  1. Fill in the blank: The ______ file contains method declarations, while the ______ file contains method implementations.

  1. True or false: #pragma once and #ifndef guards serve different purposes.

  1. Fill in the blank: The :: operator is called the ______ operator.

  1. True or false: Encapsulation means hiding the interface from the implementation.

Answers: 1. False (it is primitive). 2. .h; .cpp. 3. False (same purpose). 4. Scope resolution. 5. False (it separates them, but the interface is the public-facing part).


Practice Q&A

Q: What is the difference between a primitive type and a user-defined type in C++? Give an example of each.

A: A primitive type is built into the language (e.g. int, double). A user-defined type is one the programmer creates using a class (e.g. Cube). Primitive types are ready to use; user-defined types require a class definition.

Q: Explain encapsulation and why it is useful.

A: Encapsulation separates the interface (what a class does) from the implementation (how it does it). This is useful because you can change internal logic without affecting code that depends on the class, as long as the interface stays the same.

Q: Given a class called Rectangle, write the line of code that would appear in rectangle.cpp to begin implementing a method called getArea that returns a double.

A: double Rectangle::getArea() { ... } The Rectangle:: scope resolution tells the compiler this getArea belongs to the Rectangle class.

Q: What problem do inclusion guards solve?

A: They prevent a header file from being included multiple times in a single compilation, which would cause duplicate definition errors.

Q: In the .h / .cpp split, where does the class get defined, and where do the methods get implemented?

A: The class is defined in the .h file (by listing its members). The methods are implemented in the .cpp file (by writing their bodies).


Connections to Other Topics

This lecture's class structure and .h / .cpp split is the foundation for every data structure in CS 225. When you later build linked lists, trees, and graphs, each one will be a class with its own header and source file. Encapsulation also connects directly to abstract data types (ADTs), where the interface is defined independently of any particular implementation. Understanding scope resolution now will save you confusion when you encounter inheritance and namespaces later in the course.


Related Terms / Search Tags

C++ variables, primitive types, user-defined types, int, char, double, bool, float, pointer, class definition, class declaration, encapsulation, interface vs implementation, API, header file, .h file, source file, .cpp file, inclusion guard, pragma once, ifndef define endif, scope resolution operator, double colon operator, CS 225, UIUC, data structures, object-oriented programming, OOP basics, C++ classes intro