Classes & Objects: Encapsulation Fundamentals

ক্লাস ও অবজেক্ট — ক্যাপসুলেশন

Read: ~35 min 16 practice problems

1. The Class — A Custom Type

A class bundles state (data members) with behavior (member functions). Each instance of the class is an object with its own copy of the data.

class.cpp
#include <iostream>
#include <string>

class Person {
private:
    std::string name_;
    int         age_;

public:
    Person(std::string name, int age)
        : name_(std::move(name)), age_(age) {}

    void greet() const {
        std::cout << "Hi, I'm " << name_ << ", " << age_ << "\n";
    }

    void birthday() { ++age_; }
    int age() const { return age_; }
};

int main() {
    Person sara{"Sara", 21};
    sara.greet();
    sara.birthday();
    std::cout << "Now: " << sara.age() << "\n";
}

2. Access Specifiers

SpecifierVisible to
privateOnly member functions of the class
protectedClass and its subclasses
publicEveryone
Encapsulation rule Make data private. Expose only the operations the class needs. This protects invariants.

3. Member vs Non-member Functions

Methods on the class can read/write its private data. Free (non-member) functions can only use the public interface. Free functions are often a better choice when the operation doesn't need privileged access.

4. The this Pointer

Inside a non-static member function, this is a pointer to the current object.

this.cpp
class Counter {
    int n_ = 0;
public:
    Counter& increment() { ++this->n_; return *this; }
    int value() const { return n_; }
};

// Allows: c.increment().increment().increment();

5. const Member Functions

A function marked const after the parameter list cannot modify the object. You can call const methods on const objects.

const-correctness rule Mark every member function that doesn't change state as const. Otherwise const users can't call it.

6. Class Invariants

An invariant is a condition that must always be true between calls to public methods. The class enforces it:

invariant.cpp
class Fraction {
    int num_, denom_;
public:
    // Invariant: denom_ != 0
    Fraction(int n, int d) : num_(n), denom_(d) {
        if (d == 0) throw std::invalid_argument{"zero denom"};
    }
    double value() const { return double(num_) / denom_; }
};

7. Practice Problems

  1. Define class Point2D with x, y and a method distanceTo.
    ✨ Show Answer
    class Point2D {
        double x_, y_;
    public:
        Point2D(double x, double y) : x_(x), y_(y) {}
        double distanceTo(const Point2D& o) const {
            double dx = x_-o.x_, dy = y_-o.y_;
            return std::sqrt(dx*dx + dy*dy);
        }
    };
  2. Why make data members private?
    ✨ Show Answer

    To protect invariants. If users can write directly to internals, the class can't ensure validity (e.g. denominator never 0). Public interface is the contract; private is implementation.

  3. Define a BankAccount with a non-negative balance.
    ✨ Show Answer
    class BankAccount {
        double balance_ = 0;
    public:
        void deposit(double a) {
            if (a > 0) balance_ += a;
        }
        bool withdraw(double a) {
            if (a > 0 && a <= balance_) { balance_ -= a; return true; }
            return false;
        }
        double balance() const { return balance_; }
    };
  4. Why mark balance() as const?
    ✨ Show Answer

    It only reads. Marking it const allows it to be called on a const BankAccount.

  5. What's the difference between struct and class?
    ✨ Show Answer

    Default access. struct defaults to public; class defaults to private. Convention: struct for data bags, class for encapsulated objects.

  6. Define a member function that returns *this for chaining.
    ✨ Show Answer

    See section 4 — Counter& increment() { ++n_; return *this; }.

  7. What is an aggregate?
    ✨ Show Answer

    A class without user-declared constructors, virtual functions, or private/protected non-static data. You can use brace-init with members directly: Point{1, 2}.

  8. Add a static member counting all Person instances.
    ✨ Show Answer
    class Person {
        static int count_;
    public:
        Person() { ++count_; }
        ~Person() { --count_; }
        static int alive() { return count_; }
    };
    int Person::count_ = 0;
  9. Define operator== as default for a struct (C++20).
    ✨ Show Answer
    struct Point { int x, y; bool operator==(const Point&) const = default; };
  10. What's a getter? A setter?
    ✨ Show Answer

    Getter: const method returning the value of a member. Setter: method that assigns to a member, possibly with validation. Don't add them blindly — only when truly needed by clients.

  11. Why is C++ method dispatch usually compile-time?
    ✨ Show Answer

    By default, member calls are statically bound. Only virtual functions are dispatched at runtime via vtable.

  12. Define a class with a private helper method.
    ✨ Show Answer
    class X {
        int compute() const { return 42; } // private helper
    public:
        int publicAPI() const { return compute() + 1; }
    };
  13. What does Person p; do — calls which constructor?
    ✨ Show Answer

    Default constructor. If you didn't write one, the compiler tries to generate it; if a member is uninitializable (e.g. a const member with no default), it fails.

  14. Define a class member with default value = 0.
    ✨ Show Answer
    class X { int n = 0; }; // in-class member init
  15. Use a member init list in a constructor.
    ✨ Show Answer
    Person(std::string n, int a) : name_(std::move(n)), age_(a) {}

    Initializes members directly — more efficient than assigning in the body.

  16. Why prefer member init list over body assignment?
    ✨ Show Answer

    The body runs after all members are default-constructed. Init list constructs members directly with the given args — saving a default construction + assignment. For const/reference members, init list is required.

Summary

A class bundles data and behavior. Make data private; expose a clean public interface. Mark methods const when they don't modify state. Use member init list for efficient construction. The class enforces invariants the language alone can't.

Next Module → Constructors, Destructors & RAII.