08

Module 8: Object-Oriented Programming (Classes)

Chapter 8 • Intermediate

60 min

Object-Oriented Programming (Classes)

Object-Oriented Programming (OOP) is a programming paradigm that organizes code around objects and classes. It's one of the most important concepts in modern C++.

What is OOP?

Object-Oriented Programming models real-world entities as objects that have:

  • Attributes (data/state)
  • Behaviors (functions/methods)

Key Principles:

  • Encapsulation: Bundling data and methods together
  • Abstraction: Hiding implementation details
  • Inheritance: Creating new classes from existing ones
  • Polymorphism: Same interface, different implementations

What is a Class?

A class is a blueprint or template for creating objects. It defines:

  • Data members (attributes/variables)
  • Member functions (methods/behaviors)

Analogy: A class is like a blueprint for a house, and objects are the actual houses built from that blueprint.

Class Syntax

Basic Structure:

cpp.js
class ClassName {
private:
    // Private members (only accessible within class)
    
public:
    // Public members (accessible from outside)
    
protected:
    // Protected members (accessible in class and derived classes)
};

Access Specifiers

Control who can access class members:

  • private: Only accessible within the class (default)
  • public: Accessible from anywhere
  • protected: Accessible in class and derived classes

Creating a Simple Class

Example:

cpp.js
class Rectangle {
private:
    double width;
    double height;
    
public:
    // Constructor
    Rectangle(double w, double h) {
        width = w;
        height = h;
    }
    
    // Member functions
    double getArea() {
        return width * height;
    }
    
    double getPerimeter() {
        return 2 * (width + height);
    }
    
    void setDimensions(double w, double h) {
        width = w;
        height = h;
    }
};

Objects

An object is an instance of a class:

cpp.js
Rectangle rect(5.0, 3.0);  // Create object
double area = rect.getArea();  // Call method

Constructors

Constructors initialize objects when they're created.

Default Constructor

No parameters:

cpp.js
class Rectangle {
private:
    double width, height;
    
public:
    Rectangle() {  // Default constructor
        width = 0;
        height = 0;
    }
};

Parameterized Constructor

Takes parameters:

cpp.js
Rectangle(double w, double h) {
    width = w;
    height = h;
}

Constructor Initialization List (Preferred)

More efficient:

cpp.js
Rectangle(double w, double h) : width(w), height(h) {
    // Body can be empty
}

Copy Constructor

Creates object from another object:

cpp.js
Rectangle(const Rectangle& other) {
    width = other.width;
    height = other.height;
}

Destructors

Clean up when object is destroyed:

cpp.js
~Rectangle() {
    // Cleanup code (if needed)
    // Called automatically when object goes out of scope
}

Note: Destructor name starts with ~ and has no parameters.

Member Functions

Functions defined inside a class:

Inside Class Definition

cpp.js
class Rectangle {
public:
    double getArea() {
        return width * height;
    }
};

Outside Class Definition

cpp.js
class Rectangle {
public:
    double getArea();  // Declaration
};

double Rectangle::getArea() {  // Definition
    return width * height;
}

this Pointer

Points to the current object:

cpp.js
class Rectangle {
private:
    double width;
    
public:
    void setWidth(double width) {
        this->width = width;  // this->width refers to member
    }
};

Complete Example

cpp.js
#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;
    int age;
    double gpa;
    
public:
    // Constructor
    Student(string n, int a, double g) : name(n), age(a), gpa(g) {}
    
    // Getter methods
    string getName() const { return name; }
    int getAge() const { return age; }
    double getGpa() const { return gpa; }
    
    // Setter methods
    void setName(string n) { name = n; }
    void setAge(int a) { age = a; }
    void setGpa(double g) { gpa = g; }
    
    // Other methods
    void display() const {
        cout << "Name: " << name << ", Age: " << age 
             << ", GPA: " << gpa << endl;
    }
    
    bool isHonorStudent() const {
        return gpa >= 3.5;
    }
};

int main() {
    Student student1("Alice", 20, 3.8);
    Student student2("Bob", 19, 3.2);
    
    student1.display();
    student2.display();
    
    if (student1.isHonorStudent()) {
        cout << student1.getName() << " is an honor student!" << endl;
    }
    
    return 0;
}

Const Member Functions

Functions that don't modify object state:

cpp.js
double getArea() const {
    return width * height;  // Cannot modify members
}

Benefits:

  • Can be called on const objects
  • Clearly indicates function doesn't modify state
  • Better compiler optimization

Static Members

Belong to the class, not individual objects:

Static Data Member

cpp.js
class Counter {
private:
    static int count;  // Shared by all objects
    
public:
    Counter() { count++; }
    static int getCount() { return count; }
};

int Counter::count = 0;  // Definition outside class

Static Member Function

cpp.js
static int getCount() {
    return count;  // Can only access static members
}

Friend Functions

Functions that can access private members:

cpp.js
class Rectangle {
private:
    double width, height;
    
    friend void printDimensions(Rectangle& r);
};

void printDimensions(Rectangle& r) {
    cout << r.width << " x " << r.height << endl;
}

Operator Overloading

Define how operators work with your class:

cpp.js
class Vector {
private:
    double x, y;
    
public:
    Vector(double x, double y) : x(x), y(y) {}
    
    // Overload + operator
    Vector operator+(const Vector& other) {
        return Vector(x + other.x, y + other.y);
    }
    
    // Overload == operator
    bool operator==(const Vector& other) {
        return (x == other.x && y == other.y);
    }
};

// Usage
Vector v1(1, 2);
Vector v2(3, 4);
Vector v3 = v1 + v2;  // Uses overloaded +

Best Practices

  1. Use access specifiers appropriately (private by default)
  2. Provide constructors for initialization
  3. Use const for member functions that don't modify state
  4. Use initialization lists in constructors
  5. Encapsulate data (make data members private)
  6. Provide getters/setters when needed
  7. Keep classes focused (single responsibility)
  8. Use meaningful names for classes and members

Common Mistakes

  • ❌ Forgetting to initialize members
  • ❌ Not using const for getter functions
  • ❌ Making everything public (breaks encapsulation)
  • ❌ Not providing constructors when needed
  • ❌ Forgetting to define static members outside class
  • ❌ Circular dependencies between classes

Next Steps

In future modules, we'll cover:

  • Inheritance: Creating derived classes
  • Polymorphism: Virtual functions and dynamic binding
  • Abstract Classes: Pure virtual functions
  • Templates: Generic programming

Summary

Classes are the foundation of OOP in C++. They allow you to:

  • Organize related data and functions
  • Create reusable code
  • Model real-world entities
  • Implement encapsulation and abstraction

Master classes, and you'll be ready for advanced OOP concepts!

Hands-on Examples

Basic Class Example

#include <iostream>
#include <string>
using namespace std;

class Rectangle {
private:
    double width;
    double height;
    
public:
    // Constructor
    Rectangle(double w, double h) : width(w), height(h) {}
    
    // Getter methods
    double getWidth() const { return width; }
    double getHeight() const { return height; }
    
    // Setter methods
    void setWidth(double w) { width = w; }
    void setHeight(double h) { height = h; }
    
    // Member functions
    double getArea() const {
        return width * height;
    }
    
    double getPerimeter() const {
        return 2 * (width + height);
    }
    
    void display() const {
        cout << "Rectangle: " << width << " x " << height << endl;
        cout << "Area: " << getArea() << endl;
        cout << "Perimeter: " << getPerimeter() << endl;
    }
};

int main() {
    Rectangle rect(5.0, 3.0);
    rect.display();
    
    rect.setWidth(10.0);
    rect.setHeight(6.0);
    cout << "\nAfter modification:" << endl;
    rect.display();
    
    return 0;
}

Classes bundle data (width, height) and functions (getArea, getPerimeter) together. Private members are encapsulated, public methods provide interface. Constructors initialize objects, getters/setters control access.