Classes and Objects — Class Definitions, Access Specifiers, this Pointer
In this tutorial, you will learn about Classes and Objects. We cover key concepts, practical examples, and best practices to help you master this topic.
C++ classes are user-defined types that encapsulate data and behavior behind public, protected, and private access specifiers, with the implicit this pointer enabling self-referencing member functions.
What You'll Learn
You will define classes with member variables and member functions, understand public, private, and protected access specifiers, use the this pointer inside member functions, create objects on the stack and heap, separate interface (header) from implementation (source file), and compare classes with structs.
Why It Matters
Classes are the foundation of object-oriented programming in C++. They let you bundle related data and operations into a single unit. The access specifier system enforces Encapsulation: you decide exactly what parts of your class are visible to users. This is how large C++ projects maintain sanity across millions of lines of code.
Learning Path
graph LR
A["10: Functions"] --> B["11: Classes & Objects"]
B --> C["12: Constructors"]
C --> D["13: Destructors"]
D --> E["14: Encapsulation"]
style A fill:#4a90d9,stroke:#2c5f8a,color:#fff
style B fill:#4a90d9,stroke:#2c5f8a,color:#fff
style C fill:#4a90d9,stroke:#2c5f8a,color:#fff
style D fill:#4a90d9,stroke:#2c5f8a,color:#fff
style E fill:#4a90d9,stroke:#2c5f8a,color:#fff
Defining a Class
#include <iostream>
#include <string>
class Rectangle {
private:
double width_;
double height_;
public:
void setDimensions(double w, double h) {
width_ = w;
height_ = h;
}
double area() const {
return width_ * height_;
}
double perimeter() const {
return 2 * (width_ + height_);
}
};
int main() {
Rectangle rect;
rect.setDimensions(5.0, 3.0);
std::cout << "Area: " << rect.area() << "\n";
std::cout << "Perimeter: " << rect.perimeter() << "\n";
return 0;
}
Access Specifiers
private: members accessible only within the class itself (default forclass)public: members accessible from anywhereprotected: members accessible within the class and derived classes (covers in Lesson 15)
class BankAccount {
private:
double balance_; // only member functions can touch this
public:
void deposit(double amount) {
if (amount > 0) balance_ += amount;
}
double getBalance() const {
return balance_;
}
};
int main() {
BankAccount account;
// account.balance_ = 1000; // Error: private
account.deposit(1000);
std::cout << account.getBalance() << "\n";
}
The this Pointer
Inside a member function, this is an implicit pointer to the object on which the function was called.
#include <iostream>
class Point {
private:
int x_, y_;
public:
void setX(int x) { this->x_ = x; }
void setY(int y) { this->y_ = y; }
void set(int x, int y) {
this->x_ = x;
this->y_ = y;
}
Point* getThis() { return this; }
void print() const {
std::cout << "(" << x_ << ", " << y_ << ")\n";
}
};
int main() {
Point p1, p2;
p1.set(3, 4);
p2.set(5, 6);
p1.print();
p2.print();
std::cout << (p1.getThis() == &p1) << "\n"; // 1 (true)
// Method chaining using this
Point* ptr = &p1;
ptr->setX(10);
ptr->setY(20);
ptr->print();
}
this is most commonly used to:
- Distinguish parameter names from member names
- Return
*thisfrom member functions to enable method chaining - Pass the current object to another function
Separating Interface from Implementation
rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle {
private:
double width_;
double height_;
public:
void setDimensions(double w, double h);
double area() const;
double perimeter() const;
};
#endif
rectangle.cpp
#include "rectangle.h"
void Rectangle::setDimensions(double w, double h) {
width_ = w;
height_ = h;
}
double Rectangle::area() const {
return width_ * height_;
}
double Rectangle::perimeter() const {
return 2 * (width_ + height_);
}
main.cpp
#include <iostream>
#include "rectangle.h"
int main() {
Rectangle r;
r.setDimensions(4, 7);
std::cout << r.area() << "\n";
}
The :: is the scope resolution operator. Rectangle::setDimensions means "the setDimensions function that belongs to the Rectangle class."
Class vs struct
struct Point {
int x; // public by default
int y;
};
class Circle {
double radius_; // private by default
public:
void setRadius(double r) { radius_ = r; }
double area() const { return 3.14159 * radius_ * radius_; }
};
int main() {
Point p;
p.x = 10; // OK: struct members are public
Circle c;
// c.radius_ = 5; // Error: private
c.setRadius(5);
}
In C++, struct and class are identical except:
structhas public access by defaultclasshas private access by default
Convention: use struct for simple data aggregates (plain old data) and class for types with invariants and private data.
Const Member Functions
class Counter {
private:
int count_ = 0;
public:
void increment() { ++count_; } // non-const
int value() const { return count_; } // const: can call on const objects
};
void printCounter(const Counter& c) {
std::cout << c.value() << "\n"; // OK: value() is const
// c.increment(); // Error: increment() is non-const
}
Mark all member functions that do not modify the object as const. This allows them to be called on const objects and references.
Common Mistakes
Mistake 1: Forgetting Semicolon After Class Definition
class MyClass { }; // semicolon required
Mistake 2: Non-const Member Called on Const Object
const Rectangle r;
r.setDimensions(3, 4); // Error if setDimensions is not const
Make all getters and read-only operations const.
Mistake 3: Accessing Private Members from Outside
class Foo { private: int x; };
Foo f;
f.x = 5; // Error
Use public getters/setters or make the member public if encapsulation is not needed.
Mistake 4: Missing Include Guard
// myclass.h — without header guard, double-inclusion causes error
Always use #ifndef, #define, #endif or #pragma once.
Mistake 5: Confusing . and ->
Rectangle r;
Rectangle* p = &r;
r.area(); // dot for objects
p->area(); // arrow for pointers
(*p).area(); // equivalent to arrow
Mistake 6: Using this Unnecessarily
void setX(int x) { x_ = x; } // fine without this-> if member names differ
Only need this-> when parameter names shadow member names.
Practice Questions
- What is the default access level in a
class? In astruct? - Write a
Timeclass with hours, minutes, seconds (private) and getters/setters (public). - What does
thispoint to inside a member function? - Why would you mark a member function as
const? - Write a class that uses method chaining (member functions returning
*this).
Challenge
Design a Fraction class with private numerator and denominator, public add, subtract, multiply, divide methods that return Fraction, and a simplify method using GCD. Mark const-correctly.
FAQ
Mini Project
Build a Student class:
#include <iostream>
#include <string>
#include <vector>
class Student {
private:
std::string name_;
std::string id_;
std::vector<double> grades_;
public:
Student(const std::string& name, const std::string& id)
: name_(name), id_(id) {}
void addGrade(double grade) {
if (grade >= 0.0 && grade <= 100.0) {
grades_.push_back(grade);
}
}
double average() const {
if (grades_.empty()) return 0.0;
double sum = 0.0;
for (double g : grades_) {
sum += g;
}
return sum / grades_.size();
}
char letterGrade() const {
double avg = average();
if (avg >= 90) return 'A';
if (avg >= 80) return 'B';
if (avg >= 70) return 'C';
if (avg >= 60) return 'D';
return 'F';
}
void print() const {
std::cout << name_ << " (" << id_ << "): "
<< average() << "% -> " << letterGrade() << "\n";
}
};
int main() {
Student alice("Alice Smith", "S12345");
alice.addGrade(85);
alice.addGrade(92);
alice.addGrade(78);
alice.print();
}
What's Next
Classes let you define custom types. The next lesson covers constructors: default, parameterized, copy, and move constructors, plus the member initializer list.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro