Backend Systemsbeginner
C++ Basics & OOP
Learn C++ fundamentals: classes, constructors, destructors, access specifiers, operator overloading, and how C++ improves on C.
Asma HafeezApril 17, 20265 min read
cppoopclassesconstructorsc-plus-plus
C++ Basics & OOP
C++ extends C with classes, RAII, templates, and the STL. It's used for game engines, compilers, trading systems, and anywhere performance matters alongside abstraction.
Hello World
CPP
#include <iostream> // std::cout, std::cin
#include <string> // std::string
int main() {
std::string name;
std::cout << "Enter your name: ";
std::cin >> name;
std::cout << "Hello, " << name << "!\n";
return 0;
}Bash
g++ -std=c++20 hello.cpp -o hello
./hellousing namespace std
CPP
#include <iostream>
using namespace std; // avoid typing std:: everywhere
int main() {
cout << "Hello!\n"; // no std:: needed
}References — C++'s Alternative to Pointers
CPP
int x = 10;
int& ref = x; // ref is an alias for x
ref = 20; // modifies x directly
cout << x; // 20
// Pass by reference — modifies the original
void double_it(int& n) {
n *= 2;
}
int val = 5;
double_it(val);
cout << val; // 10
// Const reference — read-only access without copying
void print(const std::string& s) {
cout << s << "\n"; // efficient — no copy
}Classes
CPP
#include <iostream>
#include <string>
class Person {
private: // only accessible inside the class
std::string name_;
int age_;
public: // accessible from anywhere
// Constructor
Person(const std::string& name, int age)
: name_(name), age_(age) {} // initializer list — preferred
// Getters
const std::string& name() const { return name_; }
int age() const { return age_; }
// Method
void greet() const {
std::cout << "Hi, I'm " << name_ << ", age " << age_ << "\n";
}
// toString equivalent
std::string toString() const {
return "Person(" + name_ + ", " + std::to_string(age_) + ")";
}
};
Person alice("Alice", 30);
alice.greet(); // Hi, I'm Alice, age 30
std::cout << alice.name() << "\n"; // Alice
std::cout << alice.toString() << "\n"; // Person(Alice, 30)Constructors and Destructors
CPP
class Buffer {
private:
int* data_;
int size_;
public:
// Constructor — allocates resource
explicit Buffer(int size)
: size_(size), data_(new int[size]) {
std::cout << "Buffer created, size " << size << "\n";
}
// Destructor — automatically called when object goes out of scope
~Buffer() {
delete[] data_; // free heap memory
std::cout << "Buffer destroyed\n";
}
// Copy constructor — deep copy
Buffer(const Buffer& other)
: size_(other.size_), data_(new int[other.size_]) {
std::copy(other.data_, other.data_ + size_, data_);
}
// Copy assignment
Buffer& operator=(const Buffer& other) {
if (this == &other) return *this; // self-assignment check
delete[] data_;
size_ = other.size_;
data_ = new int[size_];
std::copy(other.data_, other.data_ + size_, data_);
return *this;
}
int size() const { return size_; }
int& operator[](int i) { return data_[i]; }
};
{
Buffer buf(5); // Constructor called
buf[0] = 10;
buf[1] = 20;
} // Destructor called automatically — no free() needed!RAII — Resource Acquisition Is Initialization
RAII is the C++ idiom where resources are tied to object lifetime.
CPP
// RAII file wrapper
class File {
FILE* handle_;
public:
explicit File(const char* path, const char* mode)
: handle_(fopen(path, mode)) {
if (!handle_) throw std::runtime_error("Cannot open file");
}
~File() {
if (handle_) fclose(handle_); // always closed, even on exception
}
// Disable copy
File(const File&) = delete;
File& operator=(const File&) = delete;
void writeLine(const std::string& line) {
fprintf(handle_, "%s\n", line.c_str());
}
};
try {
File f("output.txt", "w");
f.writeLine("Hello from RAII");
} // f.~File() called here — file closed automaticallyInheritance
CPP
class Animal {
protected:
std::string name_;
public:
Animal(const std::string& name) : name_(name) {}
virtual void speak() const { // virtual — allows overriding
std::cout << name_ << " makes a sound\n";
}
virtual ~Animal() = default; // virtual destructor — essential for polymorphism
};
class Dog : public Animal {
public:
Dog(const std::string& name) : Animal(name) {}
void speak() const override { // override — compile-time check
std::cout << name_ << " barks: WOOF!\n";
}
void fetch() const {
std::cout << name_ << " fetches the ball!\n";
}
};
class Cat : public Animal {
public:
Cat(const std::string& name) : Animal(name) {}
void speak() const override {
std::cout << name_ << " meows\n";
}
};
// Polymorphism via base class pointer
std::vector<std::unique_ptr<Animal>> animals;
animals.push_back(std::make_unique<Dog>("Rex"));
animals.push_back(std::make_unique<Cat>("Whiskers"));
for (const auto& a : animals) {
a->speak(); // polymorphic dispatch
}Operator Overloading
CPP
class Vector2D {
public:
double x, y;
Vector2D(double x = 0, double y = 0) : x(x), y(y) {}
// +, -, * operators
Vector2D operator+(const Vector2D& other) const {
return {x + other.x, y + other.y};
}
Vector2D operator*(double scalar) const {
return {x * scalar, y * scalar};
}
bool operator==(const Vector2D& other) const {
return x == other.x && y == other.y;
}
double length() const {
return std::sqrt(x * x + y * y);
}
// Stream output
friend std::ostream& operator<<(std::ostream& os, const Vector2D& v) {
return os << "(" << v.x << ", " << v.y << ")";
}
};
Vector2D a{3, 4}, b{1, 2};
Vector2D c = a + b;
std::cout << c << "\n"; // (4, 6)
std::cout << a.length() << "\n"; // 5.0Structs in C++
In C++, struct and class are nearly identical — the only difference is default access (public for struct, private for class).
CPP
struct Point {
double x, y;
// Methods are fine in structs
double distanceTo(const Point& other) const {
double dx = x - other.x, dy = y - other.y;
return std::sqrt(dx*dx + dy*dy);
}
};
Point p1{0, 0}, p2{3, 4};
std::cout << p1.distanceTo(p2); // 5.0Key Takeaways
- Use references instead of pointers when the value can't be null
- RAII — tie resource lifetime to object lifetime; destructors handle cleanup
- Mark methods
constwhen they don't modify the object — enables use on const objects - Use
virtualfor methods you want subclasses to override; always addvirtual ~destructor overridekeyword catches typos — use it on every overridden method
Enjoyed this article?
Explore the Backend Systems learning path for more.
Found this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.