Land the job you want — prepare
with Real interviews Q&A
Curated interview questions, company-wise guides and coding rounds. Practice mock interviews, improve with feedback, and track your progress.
C++ is an object-oriented programming language developed by Bjarne Stroustrup in 1979 at Bell Labs. It acts as an extension of the C programming language and supports procedural, object-oriented, and generic concepts.
#include <iostream>
class Welcome {
public:
void sayHello() {
std::cout << "Welcome to Object-Oriented C++ Programming!" << std::endl;
}
};
int main() {
Welcome bjarne;
bjarne.sayHello();
return 0;
}The fundamental principles of Object-Oriented Programming (OOP) include:
- Encapsulation: Binding data and methods into a single class interface while preventing direct external access.
- Abstraction: Exposing crucial APIs while hiding secondary execution mechanics.
- Inheritance: Creating hierarchical patterns where derived classes absorb attributes of base classes.
- Polymorphism: Allowing dynamic method dispatch based on context.
class BankAccount {
private:
double balance; // Encapsulation: private variable
public:
BankAccount(double initial_balance) : balance(initial_balance) {}
void deposit(double amount) { // Abstraction: hidden internals
if (amount > 0) balance += amount;
}
double getBalance() const { return balance; }
};A class is a user-defined template or blueprint for creating objects. It encapsulates attributes (data members) and actions (member functions) into a unified object definition.
class Car {
private:
std::string model;
int year;
public:
void setDetails(std::string m, int y) {
model = m;
year = y;
}
};An object is a runtime instance of a class. It represents an entity in memory that possesses properties and can invoke associated member functions.
// Instantiating objects on Stack and Heap
Car stackCar; // Stack-allocated
stackCar.setDetails("Tesla Model S", 2024);
Car* heapCar = new Car(); // Heap-allocated using new
heapCar->setDetails("Porsche Taycan", 2025);
delete heapCar; // Avoid memory leakA constructor is a special member function that initializes objects of its class. It shares the same name as the class and runs automatically when an instance is instantiated.
class Box {
private:
double width;
public:
// 1. Default Constructor
Box() : width(1.0) {}
// 2. Parameterized Constructor
Box(double w) : width(w) {}
// 3. Copy Constructor
Box(const Box& other) {
width = other.width;
}
};A destructor is a member function called automatically when an object goes out of scope or is deleted. It is designated with a tilde ~ prefix and is used to release dynamic resources like memory or file locks.
class ResourceManager {
private:
int* dataBuffer;
public:
ResourceManager(int size) {
dataBuffer = new int[size]; // Allocating resources
}
~ResourceManager() {
delete[] dataBuffer; // Destructor: Releases resources to prevent leaks
}
};Function Overloading is a feature allowing multiple functions to declare identical names within the same scope, provided their signature parameters (type, number, or order) are distinct.
class Calculator {
public:
// Function Overloading: Same name, different parameters
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 lets you redefine standard arithmetic or relational operators (`+`, `-`, `==`, etc.) to execute custom operations on user-defined types (classes/structs).
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overloading the '+' operator for Complex objects
Complex operator + (const Complex& obj) {
Complex temp;
temp.real = real + obj.real;
temp.imag = imag + obj.imag;
return temp;
}
};Inheritance is a process where a subclass (derived class) inherits properties, members, and behavior of a superclass (base class), supporting massive code reusability.
class Base {
public:
void show() { std::cout << "Base Class" << std::endl; }
};
// Inheritance: Derived class acquires Base class properties
class Derived : public Base {
public:
void display() { std::cout << "Derived Class" << std::endl; }
};Polymorphism ("many forms") means the ability of a function, message, or object to execute differently based on the context of invocation. It supports both static (compile-time) and dynamic (runtime) behaviors.
class Animal {
public:
virtual void makeSound() { // Enables dynamic binding
std::cout << "Some animal sound..." << std::endl;
}
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Woof! Woof!" << std::endl;
}
};Encapsulation wraps data members and the member functions that manipulate them inside a unified class scope, protecting objects from external direct state mutations.
class SecuredData {
private:
int confidentialKey; // Direct access restricted
public:
// Encapsulation: Access managed via controlled methods
void setKey(int k) {
if (k > 1000) confidentialKey = k;
}
int getKey() const { return confidentialKey; }
};Abstraction simplifies architecture by exposing only abstract public APIs while keeping private low-level calculations completely encapsulated and hidden.
// Interface Class (Pure Virtual Class)
class AbstractDevice {
public:
virtual void powerOn() = 0; // Pure Virtual Function (Abstraction)
virtual void powerOff() = 0;
};A namespace is a modular boundary used to group global class declarations and function modules together, completely avoiding naming collision hazards across multiple external libraries.
namespace EnterpriseMath {
int compute(int x, int y) { return x * y; }
}
namespace ScientificMath {
double compute(double x, double y) { return x + y; }
}A pointer is a data variable that holds the raw memory address of another variable in system storage. It is defined using the asterisk symbol *.
int value = 42;
int* ptr = &value; // Pointer stores address of value
std::cout << ptr; // Prints memory address (e.g., 0x7fff...)
std::cout << *ptr; // Dereferencing: Prints 42A reference variable is an immutable alias or nickname pointing directly to an existing variable. It is declared using the ampersand symbol & and cannot be modified to point to other addresses after initialization.
int original = 100;
int& ref = original; // Reference: Alias to original variable
ref = 200; // Modifies both ref and original
std::cout << original; // Prints 200Both support member functions and inheritance patterns. However, structural differences include:
- struct: Members and inheritance configurations default to
publicaccessibility. - class: Members and inheritance configurations default to
privateaccessibility.
struct StructNode {
int id; // Public by default
};
class ClassNode {
int id; // Private by default
};A virtual function is declared with the virtual keyword in a base class and overridden in subclasses. It ensures the compiler triggers the correct dynamic method dispatch at runtime based on the actual object.
class BaseClass {
public:
virtual void display() {
std::cout << "Dynamic display of Base" << std::endl;
}
};A pure virtual function is assigned a signature equal to zero (= 0) and contains no implementation in the base class. It forces derived classes to override it and makes the base class an abstract interface.
class AbstractRenderer {
public:
// Pure virtual function forces derived classes to override it
virtual void render() = 0;
};The Standard Template Library (STL) is a standard library of templates that provides data structures, algorithms, and iterators, such as std::vector, std::map, or std::sort.
#include <vector>
#include <algorithm>
std::vector<int> numbers = {3, 1, 4, 1, 5};
std::sort(numbers.begin(), numbers.end()); // STL sorting algorithmTemplates are compile-time mechanisms supporting type-independent code reuse. They let you compile single generic classes or methods that automatically scale to handle diverse parameter types (e.g. integers, floats, or custom structs).
// Class Template for generic type safety
template <typename T>
class Stack {
private:
T elements[100];
int topIndex = -1;
public:
void push(T val) { elements[++topIndex] = val; }
};C++ structures runtime safety utilizing exception handling keywords: try (wraps execution blocks),throw (triggers exceptions on runtime failures), and catch (handles exceptions safely).
try {
int divisor = 0;
if (divisor == 0) {
throw std::runtime_error("Division by zero!");
}
} catch (const std::exception& e) {
std::cout << "Exception Caught: " << e.what() << std::endl;
}A friend function is declared inside a class scope with the friend keyword. It grants an external non-member function or helper class full access permission to private and protected class variables.
class PrivateBox {
private:
int passcode = 1234;
// Friend function declaration
friend void unlockBox(const PrivateBox& b);
};
void unlockBox(const PrivateBox& b) {
std::cout << b.passcode; // Can access private members
}A deep copy allocates a completely fresh block of heap memory when copying an object. It duplicates the actual underlying values rather than just copying pointer addresses.
class DeepCopyExample {
public:
int* ptr;
DeepCopyExample(int val) { ptr = new int(val); }
// Deep Copy Constructor: Allocates new memory
DeepCopyExample(const DeepCopyExample& other) {
ptr = new int(*other.ptr);
}
~DeepCopyExample() { delete ptr; }
};A shallow copy duplicates only the reference pointer addresses of an object. The copied and original objects end up pointing to the exact same heap memory addresses, which can lead to double-free bugs.
class ShallowCopyExample {
public:
int* ptr;
ShallowCopyExample(int val) { ptr = new int(val); }
// Shallow Copy Constructor: Copies pointer address directly
ShallowCopyExample(const ShallowCopyExample& other) {
ptr = other.ptr; // Dangerous: double free hazard!
}
};The const keyword enforces compile-time read-only constraints, protecting variables or pointer targets from modification, and ensuring member functions do not alter object state.
const int MaxLimit = 100; // Const value
class ConstDemo {
public:
// Const Method: Guaranteed not to modify member variables
void display() const {
std::cout << "ReadOnly display" << std::endl;
}
};An inline function is a compiler hint requesting that function calls be expanded directly into inline assembly instructions. This optimizes performance by eliminating stack frame call overhead for small functions.
// Request compile-time expansion to reduce function call overhead
inline int square(int x) {
return x * x;
}A static member belongs to the class itself rather than to individual object instances. There is only one shared copy of the variable or function allocated for all instances.
class SharedMetrics {
public:
static int globalCounter; // Shared across all instances
static void increment() { globalCounter++; }
};
int SharedMetrics::globalCounter = 0; // Out-of-class definitionThe mutable keyword allows specific member variables to be modified even when the enclosing object is marked as const (e.g., for mutex locking or caching inside read-only APIs).
class CacheDemo {
private:
mutable int accessCount = 0;
public:
// Mutable variable can be changed inside a const method
void readData() const {
accessCount++;
}
};C++ allocates memory dynamically on the heap during runtime using the new operator, and deallocates it using the delete or delete[] (for arrays) operators.
// Allocating single variable
int* scalarPtr = new int(5);
// Allocating array dynamically
int* arrPtr = new int[10];
// Deallocating safely
delete scalarPtr;
delete[] arrPtr;Introduced in C++11, a lambda expression is an inline anonymous function. It lets you write short callbacks and predicates right where they are needed, supporting capture lists to access local scope variables.
auto sum = [](int a, int b) -> int {
return a + b;
};
int res = sum(10, 20); // Lambda returns 30Resource Acquisition Is Initialization (RAII) is a core C++ design pattern. It ties resource lifecycles (file descriptors, sockets, memory) directly to the scope lifetime of an object, acquiring resources in the constructor and releasing them automatically in the destructor.
class RAIIFile {
private:
FILE* fileHandle;
public:
RAIIFile(const char* filepath) {
fileHandle = fopen(filepath, "r"); // Resource acquired on init
}
~RAIIFile() {
if (fileHandle) fclose(fileHandle); // Resource released on destruction
}
};A smart pointer is an RAII-based wrapper class that manages dynamic memory. It automatically deallocates heap resources when the pointer goes out of scope, eliminating manual delete calls. Common types are `unique_ptr` and `shared_ptr`.
#include <memory>
// Unique Pointer: Exclusive ownership
std::unique_ptr<int> uPtr = std::make_unique<int>(10);
// Shared Pointer: Shared reference-counted ownership
std::shared_ptr<int> sPtr = std::make_shared<int>(20);Introduced in C++11, move semantics allow objects to transfer ownership of their underlying heap resources to a new instance instead of deep-copying them. This improves performance by avoiding expensive allocations.
#include <utility>
class MoveDemo {
public:
int* data;
MoveDemo(int size) { data = new int[size]; }
// Move Constructor: Transfer pointers, nullify original
MoveDemo(MoveDemo&& other) noexcept {
data = other.data;
other.data = nullptr;
}
~MoveDemo() { delete[] data; }
};C++11 introduced a native concurrency library (<thread>) allowing programs to execute multiple execution paths parallelly on modern multi-core processors.
#include <thread>
void printMessage() {
std::cout << "Thread active!" << std::endl;
}
int main() {
std::thread t1(printMessage); // Dynamic parallel execution
t1.join(); // Sync main thread with execution
return 0;
}A memory leak occurs when raw heap memory allocated via the new operator is never released with corresponding delete statements, reducing available system resources over time.
void leakyFunction() {
int* ptr = new int(10); // Allocated on Heap
// Forgot to call 'delete ptr'
// Memory remains locked until program termination
}The diamond problem occurs during multiple inheritance when a class inherits from two classes that both inherit from a single common base class. This creates ambiguity, which is resolved using the virtual inheritance keyword.
class A { public: int val; };
// Virtual Inheritance avoids duplicate storage of 'A' elements
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};The constexpr keyword specifies that a function or variable is constant and can be evaluated entirely during compilation, optimizing runtime performance.
// Evaluated entirely at compile time
constexpr int getArraySize() {
return 5 * 10;
}
int myData[getArraySize()]; // Array initialization with computed sizeThe auto keyword tells the compiler to automatically deduce the type of a variable from its initialization expression during compilation.
auto score = 98.5; // Deduced as double
auto name = "Bjarne"; // Deduced as const char*
auto isOk = true; // Deduced as boolThe noexcept specifier guarantees that a function will not throw an exception, allowing the compiler to optimize the underlying call stack.
// Explicitly states that this method will never throw an exception
void safeCompute() noexcept {
// Highly optimized by the compiler
}An rvalue reference (declared with double ampersand &&) binds strictly to temporary objects, enabling safe move constructor definitions.
int&& rValueRef = 20 + 30; // Binds to temporary values
void process(int&& temp) {
std::cout << "Handling temporary: " << temp << std::endl;
}A simple program showing console output using C++ standard streams:
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}Swapping two variables by passing parameters as references:
#include <iostream>
void swapNumbers(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
swapNumbers(x, y);
std::cout << "x: " << x << ", y: " << y << std::endl;
return 0;
}Using standard algorithms (std::reverse) to reverse elements of a string:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string str = "C++Programming";
std::reverse(str.begin(), str.end());
std::cout << "Reversed string: " << str << std::endl;
return 0;
}An efficientO(√N) complexity check loop to verify whether an integer is prime:
#include <iostream>
#include <cmath>
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i <= std::sqrt(n); ++i) {
if (n % i == 0) return false;
}
return true;
}
int main() {
int num = 29;
std::cout << num << (isPrime(num) ? " is Prime" : " is Not Prime") << std::endl;
return 0;
}Generating the Fibonacci sequence up to $N$ terms:
#include <iostream>
void printFibonacci(int terms) {
int first = 0, second = 1, next;
for (int i = 0; i < terms; ++i) {
std::cout << first << " ";
next = first + second;
first = second;
second = next;
}
}
int main() {
printFibonacci(10);
return 0;
}Iterating through an array or vector structure to identify the largest element:
#include <iostream>
#include <vector>
#include <algorithm>
int findMaxElement(const std::vector<int>& arr) {
if (arr.empty()) return -1;
return *std::max_element(arr.begin(), arr.end());
}
int main() {
std::vector<int> data = {3, 19, 4, 1, 99, 5};
std::cout << "Max Element: " << findMaxElement(data) << std::endl;
return 0;
}Calculating the factorial of a number recursively:
#include <iostream>
unsigned long long recursiveFactorial(int n) {
if (n <= 1) return 1;
return n * recursiveFactorial(n - 1);
}
int main() {
std::cout << "Factorial of 5: " << recursiveFactorial(5) << std::endl;
return 0;
}Standard initialization and loop iteration using an STL vector container:
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> programmingLanguages;
programmingLanguages.push_back("C++");
programmingLanguages.push_back("Rust");
programmingLanguages.push_back("Python");
for (const auto& lang : programmingLanguages) {
std::cout << lang << " ";
}
return 0;
}Checking if a string reads the same backwards and forwards:
#include <iostream>
#include <string>
#include <algorithm>
bool isPalindrome(std::string str) {
std::string original = str;
std::reverse(str.begin(), str.end());
return original == str;
}
int main() {
std::string word = "radar";
std::cout << word << (isPalindrome(word) ? " is Palindrome" : " is Not Palindrome") << std::endl;
return 0;
}Sorting a static array using the standard library (std::sort):
#include <iostream>
#include <algorithm>
int main() {
int arr[] = {42, 11, 88, 5, 19};
int n = sizeof(arr) / sizeof(arr[0]);
std::sort(arr, arr + n); // Sorts array values ascending
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
return 0;
}