Site

Classes — Data Grouping and Methods

Tutorial 6.0  •  C++ / Learn

6.0 What This Teaches

Classes bundle data and the functions that operate on it into one unit. This tutorial covers:

6.1 Defining a Class

class Point {
public:
    double x, y;

    Point(double x, double y) : x(x), y(y) {}

    void print() const {
        std::cout << "(" << x << ", " << y << ")";
    }
};
The class body ends with a semicolon. Members are private by default; public: makes them accessible from outside the class.

6.2 Constructors and Member Initializer Lists

class Rectangle {
public:
    double width, height;

    Rectangle(double w, double h) : width(w), height(h) {}

    // default constructor
    Rectangle() : width(1.0), height(1.0) {}
};
The : width(w), height(h) part is the member initializer list. It initializes members before the constructor body runs. Prefer it over assignment inside the body - it is more efficient and required for const members and references.

6.3 public and private

class BankAccount {
public:
    explicit BankAccount(double initial) : balance_(initial) {}

    void    deposit(double amount)  { balance_ += amount; }
    bool    withdraw(double amount) {
        if (amount > balance_) return false;
        balance_ -= amount;
        return true;
    }
    double balance() const { return balance_; }

private:
    double balance_;   // only accessible through public methods
};
Private data members are a convention enforced by the compiler: external code cannot read or write balance_ directly. This lets the class guarantee invariants (e.g., balance never goes negative).

6.4 const Member Functions

double area() const { return width * height; }
A const member function promises not to modify the object. It can be called on both const and non-const objects. Non-const member functions can only be called on non-const objects. Mark every function that does not modify state as const.

6.5 Destructors

class Logger {
public:
    Logger() { std::cout << "Logger opened\n"; }
    ~Logger() { std::cout << "Logger closed\n"; }  // called automatically on scope exit
};

void demo() {
    Logger log;    // "Logger opened"
    // ... use log ...
}   // "Logger closed" - destructor called here automatically
The destructor ~ClassName() runs automatically when the object goes out of scope or is deleted. This is RAII (Resource Acquisition Is Initialization) - resources acquired in the constructor are released in the destructor.

6.6 Example - All Together

// Classes - data grouping, constructors, member functions, access specifiers.

#include <iostream>
#include <cmath>

class Point {
public:
    double x, y;
    Point(double x, double y) : x(x), y(y) {}

    double distance_to(const Point& other) const {
        double dx = x - other.x, dy = y - other.y;
        return std::sqrt(dx * dx + dy * dy);
    }
    void print() const { std::cout << "(" << x << ", " << y << ")"; }
};

class BankAccount {
public:
    explicit BankAccount(double initial) : balance_(initial) {}
    void deposit(double amount)  { balance_ += amount; }
    bool withdraw(double amount) {
        if (amount > balance_) return false;
        balance_ -= amount; return true;
    }
    double balance() const { return balance_; }
private:
    double balance_;
};

int main() {
    Point p1{1.0, 2.0}, p2{4.0, 6.0};
    p1.print(); std::cout << " to "; p2.print();
    std::cout << " = " << p1.distance_to(p2) << "\n";

    BankAccount acct{100.0};
    acct.deposit(50.0);
    std::cout << "balance: " << acct.balance() << "\n";
    std::cout << "withdraw 200: " << (acct.withdraw(200.0) ? "ok" : "no") << "\n";
    std::cout << "withdraw 75:  " << (acct.withdraw(75.0)  ? "ok" : "no") << "\n";
    std::cout << "balance: " << acct.balance() << "\n";
    return 0;
}
(1, 2) to (4, 6) = 5
balance: 150
withdraw 200: no
withdraw 75:  ok
balance: 75

6.7 Exercise

Exercise
  • Define a Circle class with a private radius_ member, a constructor, and const methods area() and circumference().
  • Add a scale(double factor) method that multiplies the radius by factor. Confirm it is not const.
  • Write a destructor that prints "Circle destroyed" and create a Circle in a nested block to observe when it fires.

6.8 Common Mistakes

Forgetting the semicolon after the class body

class Foo {
    int x;
}   // error: expected ';' after class definition

Calling a non-const method on a const object

const BankAccount acct{100.0};
acct.deposit(50.0);   // error: cannot call non-const member function on const object
Mark all methods that do not modify state as const.

Assignment in constructor body instead of initializer list

// inefficient: default-constructs first, then assigns
Rectangle(double w, double h) { width = w; height = h; }

// preferred: direct initialization
Rectangle(double w, double h) : width(w), height(h) {}

6.9 Key Terms

TermMeaning
classUser-defined type bundling data and functions
constructorSpecial function called when an object is created
destructorSpecial function called when an object is destroyed
member initializer listInitializes members before the constructor body; preferred over assignment
publicAccess specifier: members accessible from anywhere
privateAccess specifier: members accessible only within the class
const member functionDoes not modify the object; callable on const objects
explicitPrevents implicit single-argument constructor conversions
RAIIResource Acquisition Is Initialization: acquire in constructor, release in destructor