xSKILLby Infirals
Register

C++ for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Classes and objects

Classes and object lifetime14 min readLesson 1 of 4

1.1 Bundle state and behavior

A class defines a new type. Its data members store state, and its member functions define what can be done with that state. An object is a value of the class type. Creating an object sets aside storage for its data members.

A well-designed class keeps its data consistent. A wallet should not accept a withdrawal larger than its balance, and a thermometer should not show a reading outside its valid range. Member functions are where those rules belong.

cpp
#include <iostream>
class Counter {
public:
    void click() {
        ++count;
    }
    int value() const {
        return count;
    }
private:
    int count = 0;
};
int main() {
    Counter counter;
    counter.click();
    counter.click();
    std::cout << "Clicks: " << counter.value() << "\n";
    return 0;
}

Output

Clicks: 2

1.1.1 Access control

Members listed after public: can be used by code outside the class. Members after private: can be used only by the class's own member functions. Keep data private by default and expose the operations callers need. This is encapsulation.

class and struct differ in one beginner-level detail: a class starts with private access, and a struct starts with public access. Many C++ codebases use struct for simple data with no invariants and class for types that protect state.

1.1.2 Constructors establish valid state

A constructor runs when an object is created. It has the same name as the class and no return type. Use it to initialize members so the object never starts in a broken state.

The member initializer list runs before the constructor body: Book(std::string title) : title_(title) {}. Name data members with a trailing underscore when a constructor parameter uses the same name. The distinction keeps the initializer readable.

cpp
#include <iostream>
#include <string>

class Book {
public:
    Book(std::string title, int pages)
        : title_(title), pages_(pages) {}
    void show() const {
        std::cout << title_ << ": " << pages_ << " pages\n";
    }
private:
    std::string title_;
    int pages_;
};

int main() {
    Book book("C++ Notes", 240);
    book.show();
    return 0;
}

Output

C++ Notes: 240 pages

1.1.3 Member functions and const

A member function can read or change the object's data. Add const after the parameter list when the function does not change the object: int value() const;. The compiler then rejects a modification inside that function and allows the function to be called on a const object.

Mark getters and display functions const by default. Remove const only for operations that change the object.

cpp
#include <iostream>

class Rectangle {
public:
    Rectangle(double width, double height)
        : width_(width), height_(height) {}
    double area() const {
        return width_ * height_;
    }
private:
    double width_;
    double height_;
};

int main() {
    Rectangle rect(4.0, 2.5);
    std::cout << "Area: " << rect.area() << "\n";
    return 0;
}

Output

Area: 10

1.1.4 Enforce rules inside the class

Private data and public functions let the class check every change. A deposit function can reject zero or negative amounts. A constructor can validate a starting balance. Callers then work with a type that maintains its own rules.

Returning a reference to private data lets callers change it without validation. Return a copy or a const reference for a read-only value. If a caller must edit internals, design a named operation that describes the allowed change.

cpp
#include <iostream>

class Wallet {
public:
    explicit Wallet(int start) : balance_(start) {}
    void add(int rupees) {
        if (rupees > 0) balance_ += rupees;
    }
    int balance() const { return balance_; }
private:
    int balance_;
};

int main() {
    Wallet wallet(50);
    wallet.add(25);
    wallet.add(-10);
    std::cout << "Balance: " << wallet.balance() << "\n";
    return 0;
}

Output

Balance: 75

1.1.5 One class, two files

Larger programs put the class declaration in a header file, such as Wallet.h, and the member function definitions in Wallet.cpp. Other source files include the header. The header tells the compiler what the class offers; the implementation file provides the bodies.

This header and source split becomes useful when a project has several files. Early practice can keep a small class in one .cpp file while you focus on syntax.

1.1.6 Construction, copying, and scope

A default constructor can be called with no arguments. The compiler generates one when the class declares no constructors. Once you add a constructor, that generated version disappears, so write a no-argument constructor if objects still need to be created without arguments.

Objects live inside the scope where they are declared and are destroyed at the end of that scope. Copying an object copies its members by default. For simple values that behavior is fine. Classes that own resources need more control, which is a later topic.

A destructor runs when an object goes out of scope. It has the class name with a leading ~ and takes no parameters. A class that opens a file or allocates memory can use it to release that resource. Simple classes often need no destructor because their members clean up themselves.

cpp
#include <iostream>
class Light {
public:
    Light() : on_(false) {}
    void toggle() {
        on_ = !on_;
    }
    void show() const {
        std::cout << (on_ ? "On" : "Off") << "\n";
    }
private:
    bool on_;
};
int main() {
    Light lamp;
    lamp.show();
    lamp.toggle();
    lamp.show();
    return 0;
}

Output

Off
On

1.1.7 Common mistakes

  • Forgetting the semicolon after the closing brace of a class.
  • Declaring a constructor with a return type.
  • Leaving a data member uninitialized.
  • Making every member public, including data.
  • Marking a function const and then trying to change a member.
  • Defining a member function outside the class without ClassName::.

1.1.8 Practice

  1. Write a Rectangle class with private width and height, a constructor, and an area() function.
  2. Add a member function that changes the width only when the new value is positive.
  3. Write a default constructor for a Light class and toggle it twice.
  4. Mark every function that does not change an object as const.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What is the difference between a class and an object?

    A class is a type definition that describes data and behavior. An object is a concrete value created from that class, with its own copy of the data members.

  • 02When does a constructor run?

    A constructor runs automatically when an object is created. It initializes the object before its member functions can be called.

  • 03Why should data members usually be private?

    Private data lets the class control every change and keep its rules in member functions. Public data can be modified without validation, which can leave the object in an invalid state.

Quiz

Check: C++ classes and encapsulation

Four questions on access control, constructors, initializer lists and const member functions.

4 questions

Question 1 of 4

0/4 answered

By default, members of a class declared with the class keyword are:

Answer all you can, then submit.