Last 30 Days
No notifications
A class is a blueprint that bundles data (members) and functions (methods) that act on it. An object is an instance.
class Point {
public:
double x, y; Point(double x, double y) : x(x), y(y) {} // constructor
double distanceTo(const Point& other) const { // method
double dx = x - other.x;
double dy = y - other.y;
return sqrt(dx*dx + dy*dy);
}
};
int main() {
Point p{3, 4};
Point q{0, 0};
cout << p.distanceTo(q); // 5
}
| Keyword | Visible to | ||
public | Everyone | ||
private | Only this class (default for class) | ||
protected | This class and derived classes |
| Default access |
struct | public | ||
class | private |
Convention: use struct for plain data bags, class when you have invariants/encapsulation.
class File {
FILE* fp;
public:
File(const string& path) { fp = fopen(path.c_str(), "r"); } // constructor
~File() { if (fp) fclose(fp); } // destructor — RAII!
};When a File object goes out of scope, its destructor runs automatically. No manual cleanup needed. This is RAII — the soul of modern C++.
Classes are how you turn raw data into safe, reusable building blocks. Modern C++ relies on classes for everything from STL containers to smart pointers.
class BankAccount {
private:
string owner; // member data (private = encapsulated)
double balance;public:
BankAccount(string owner, double initial) // constructor
: owner(std::move(owner)), balance(initial) {}
void deposit(double amount) { // method
balance += amount;
}
bool withdraw(double amount) {
if (amount > balance) return false;
balance -= amount;
return true;
}
double getBalance() const { // const method (read-only)
return balance;
}
};
Always prefer the initialiser list (after :) over assigning inside the body:
class Rect {
int w, h;
public:
Rect(int w, int h) : w(w), h(h) {} // ✅ direct init
// not:
// Rect(int W, int H) { w = W; h = H; } // ❌ default-constructs then assigns
};Required for const, references, and non-default-constructible members.
this PointerInside a non-static method, this is a pointer to the current object:
class Foo {
int x;
public:
Foo& set(int x) {
this->x = x; // disambiguate parameter from member
return *this; // chaining: foo.set(1).set(2)
}
};const MethodsA method declared const promises not to modify the object's data. Const objects can call only const methods.
class Circle {
double r;
public:
double area() const { return 3.14159 * r * r; } // doesn't change r
void scale(double f) { r *= f; } // not const — modifies r
};const Circle c{5};
c.area(); // ✅ ok
c.scale(2); // ❌ compile error — c is const
> Mark every method that doesn't modify state as const. It enables read-only usage and helps the compiler optimise.
| Kind | When |
| Default | Foo() — no args |
| Parameterised | Foo(int x) |
| Copy | Foo(const Foo& other) |
| Move | Foo(Foo&& other) (C++11) |
| Delegating | Foo() : Foo(0) {} |
class Point {
int x, y;
public:
Point() : Point(0, 0) {} // delegates
Point(int x, int y) : x(x), y(y) {}
Point(const Point& other) = default; // explicit default
};Runs automatically when the object's lifetime ends:
class Buffer {
int* data;
public:
Buffer(size_t n) : data(new int[n]) {}
~Buffer() { delete[] data; } // RAII: cleanup is guaranteed
};This is RAII (Resource Acquisition Is Initialisation) — own resources in objects so destructors clean up. Used by:
std::vector (frees the array)std::string (frees the buffer)std::unique_ptr (frees the pointee)std::lock_guard (releases the mutex)class Counter {
int count = 0; // private — outside code can't touch
public:
void inc() { ++count; }
int value() const { return count; }
};Counter c;
c.inc();
cout << c.value();
// c.count = 999; // ❌ compile error — count is private
Private data + public methods = you control how the object is used.
class Money { public: Money(double amount); };
Money m = 19.99; // ⚠️ implicit conversion from double — surprisingMark single-argument constructors explicit to forbid this:
explicit Money(double amount);
Money m = 19.99; // ❌ now an error
Money m{19.99}; // ✅ explicit constructionBelong to the class, not any instance:
class Logger {
static int count;
public:
Logger() { ++count; }
static int total() { return count; }
};
int Logger::count = 0; // definition, in a .cpp filecout << Logger::total();
friend lets a function or another class access private members. Use sparingly — usually for stream operators:
class Vec2 {
double x, y;
public:
Vec2(double x, double y) : x(x), y(y) {}
friend ostream& operator<<(ostream& os, const Vec2& v);
};
ostream& operator<<(ostream& os, const Vec2& v) {
return os << "(" << v.x << "," << v.y << ")";
}Classes can define what +, -, ==, etc. mean:
class Vec2 { /*...*/
Vec2 operator+(const Vec2& o) const { return {x + o.x, y + o.y}; }
bool operator==(const Vec2& o) const { return x == o.x && y == o.y; }
};
Vec2 a{1,2}, b{3,4};
Vec2 c = a + b; // calls operator+If your class doesn't manage a raw resource, don't write any of: copy ctor, copy assignment, move ctor, move assignment, destructor. The compiler-generated ones are correct (Rule of Zero).
If your class does own a raw resource, you typically need all five. Modern C++ avoids this by wrapping resources in unique_ptr, vector, string, etc.
| Need | Code |
| Plain data | struct Point { int x, y; }; |
| Encapsulated | class Foo { private: ... public: ... }; |
| Constructor (init list) | Foo(int x) : x_(x) {} |
| Read-only method | int get() const { ... } |
| Cleanup | destructor ~Foo() { ... } |
| Forbid implicit conv | explicit Foo(int); |
| Class-wide data | static int count; |
| Default copy/move | Foo(const Foo&) = default; |
| Forbid copy | Foo(const Foo&) = delete; |
You now understand the heart of C++ OOP. Phase 3 dives into inheritance, polymorphism, smart pointers, and templates — built on exactly these foundations.