C++ Basics
C++
#include <iostream>
#include <string>
using namespace std;
int main() {
// Output
cout << "Hello, World!" << endl;
// Variables
int age = 25;
double salary = 50000.50;
string name = "Alice";
bool isActive = true;
// Input
cout << "Enter your name: ";
cin >> name;
// getline for full line
getline(cin, name);
// Reference variable
int x = 10;
int& ref = x; // ref is alias for x
ref = 20; // x is now 20
// Pointers (similar to C)
int* ptr = &x;
cout << *ptr << endl; // 20
// Constants
const int MAX = 100;
constexpr int SIZE = 50; // Compile-time constant
// Auto type deduction
auto num = 42; // int
auto pi = 3.14; // double
auto text = "Hello"; // const char*
return 0;
}
Object-Oriented Programming
C++
// Class definition
class Person {
private: // Access modifier
string name;
int age;
protected:
string id;
public:
// Constructor
Person(string n, int a) : name(n), age(a) {
cout << "Constructor called" << endl;
}
// Default constructor
Person() : name("Unknown"), age(0) {}
// Copy constructor
Person(const Person& other) {
name = other.name;
age = other.age;
}
// Destructor
~Person() {
cout << "Destructor called" << endl;
}
// Getters
string getName() const { return name; }
int getAge() const { return age; }
// Setters
void setName(string n) { name = n; }
void setAge(int a) {
if (a >= 0) age = a;
}
// Method
void display() const {
cout << "Name: " << name << ", Age: " << age << endl;
}
// Static member
static int count;
static int getCount() { return count; }
};
int Person::count = 0; // Initialize static member
int main() {
Person p1("Alice", 25);
Person p2 = p1; // Copy constructor
p1.display();
p2.setAge(30);
Person* ptr = new Person("Bob", 30);
ptr->display();
delete ptr; // Don't forget to free!
return 0;
}
Inheritance
C++
// Base class
class Animal {
protected:
string name;
public:
Animal(string n) : name(n) {}
void eat() { cout << name << " is eating" << endl; }
};
// Single inheritance
class Dog : public Animal {
public:
Dog(string n) : Animal(n) {}
void bark() { cout << name << " says Woof!" << endl; }
};
// Multiple inheritance
class Swimmer {
public:
void swim() { cout << "Swimming..." << endl; }
};
class Duck : public Animal, public Swimmer {
public:
Duck(string n) : Animal(n) {}
void quack() { cout << name << " says Quack!" << endl; }
};
// Multilevel inheritance
class Puppy : public Dog {
public:
Puppy(string n) : Dog(n) {}
void play() { cout << name << " is playing" << endl; }
};
// Access specifiers in inheritance:
// public : base public->public, protected->protected
// protected : base public->protected, protected->protected
// private : base public->private, protected->private
int main() {
Dog dog("Buddy");
dog.eat(); // Inherited
dog.bark(); // Own method
Duck duck("Donald");
duck.eat();
duck.swim();
duck.quack();
return 0;
}
Polymorphism
C++
// Function overloading (Compile-time)
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
// Operator overloading
class Complex {
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overload + operator
Complex operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
// Overload << for output
friend ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
};
// Virtual functions (Runtime polymorphism)
class Shape {
public:
virtual double area() = 0; // Pure virtual (abstract)
virtual void draw() {
cout << "Drawing shape" << endl;
}
virtual ~Shape() {} // Virtual destructor
};
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double area() override { // Override keyword (C++11)
return 3.14159 * radius * radius;
}
void draw() override {
cout << "Drawing circle" << endl;
}
};
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() override {
return width * height;
}
};
int main() {
// Function overloading
cout << add(1, 2) << endl; // 3
cout << add(1.5, 2.5) << endl; // 4.0
// Operator overloading
Complex c1(1, 2), c2(3, 4);
cout << c1 + c2 << endl; // 4 + 6i
// Polymorphism with pointers
Shape* shapes[2];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 3);
for (int i = 0; i < 2; i++) {
shapes[i]->draw();
cout << "Area: " << shapes[i]->area() << endl;
delete shapes[i];
}
return 0;
}
Standard Template Library (STL)
C++
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
// Vector - Dynamic array
vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6);
vec.pop_back();
vec.insert(vec.begin() + 2, 10);
vec.erase(vec.begin());
int size = vec.size();
bool empty = vec.empty();
// Iterate
for (int x : vec) cout << x << " ";
for (auto it = vec.begin(); it != vec.end(); it++) cout << *it;
// Map - Key-value pairs
map<string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
ages.insert({"Charlie", 35});
if (ages.find("Alice") != ages.end()) {
cout << "Found: " << ages["Alice"] << endl;
}
for (auto& [key, value] : ages) { // C++17
cout << key << ": " << value << endl;
}
// Set - Unique sorted elements
set<int> nums = {3, 1, 4, 1, 5}; // {1, 3, 4, 5}
nums.insert(2);
nums.erase(3);
// Stack - LIFO
stack<int> s;
s.push(1);
s.push(2);
int top = s.top(); // 2
s.pop();
// Queue - FIFO
queue<int> q;
q.push(1);
q.push(2);
int front = q.front(); // 1
q.pop();
// Priority Queue - Max heap by default
priority_queue<int> pq;
pq.push(3);
pq.push(1);
pq.push(2);
int max = pq.top(); // 3
// Min heap
priority_queue<int, vector<int>, greater<int>> minPq;
// Algorithms
vector<int> v = {5, 2, 8, 1, 9};
sort(v.begin(), v.end()); // Ascending
sort(v.begin(), v.end(), greater<int>()); // Descending
reverse(v.begin(), v.end());
int maxVal = *max_element(v.begin(), v.end());
int minVal = *min_element(v.begin(), v.end());
bool found = binary_search(v.begin(), v.end(), 5);
Modern C++ (11/14/17)
C++
#include <memory>
// Lambda expressions
auto add = [](int a, int b) { return a + b; };
cout << add(3, 5) << endl;
// Lambda with capture
int multiplier = 5;
auto multiply = [multiplier](int x) { return x * multiplier; };
auto multiplyRef = [&multiplier](int x) { return x * multiplier; };
// Range-based for loop
vector<int> nums = {1, 2, 3, 4, 5};
for (int n : nums) cout << n;
for (const auto& n : nums) cout << n;
// Smart pointers
// unique_ptr - Exclusive ownership
unique_ptr<int> uptr = make_unique<int>(42);
cout << *uptr << endl;
// uptr automatically deleted when out of scope
// shared_ptr - Shared ownership
shared_ptr<int> sptr1 = make_shared<int>(100);
shared_ptr<int> sptr2 = sptr1; // Reference count = 2
cout << sptr1.use_count() << endl;
// weak_ptr - Non-owning reference
weak_ptr<int> wptr = sptr1;
// nullptr (instead of NULL)
int* ptr = nullptr;
// Move semantics
string str1 = "Hello";
string str2 = move(str1); // str1 is now empty
// Structured bindings (C++17)
pair<int, string> p = {1, "one"};
auto [num, text] = p;
// Optional (C++17)
#include <optional>
optional<int> maybeInt = 42;
if (maybeInt.has_value()) {
cout << maybeInt.value() << endl;
}
// String_view (C++17)
#include <string_view>
void print(string_view sv) { // No copy
cout << sv << endl;
}
Modern C++ Best Practices:
• Use smart pointers instead of raw pointers
• Prefer auto for type deduction
• Use range-based for loops
• Use nullptr instead of NULL
• Use constexpr for compile-time constants
• Use smart pointers instead of raw pointers
• Prefer auto for type deduction
• Use range-based for loops
• Use nullptr instead of NULL
• Use constexpr for compile-time constants