C++ evolved from C and also include the earliest implementation of object-oriented programming, it is very common in coding interviews. Following are some of the interview questions of C++:
Question 1: What is the difference between C and C++?
Answer:
- Programming paradigm – C is procedural and C++ support multi-paradigm
- Object Oriented Programming – C don’t support OOP, C++ support OOP
- Standard Template Library – C don’t have standard library for data structures like STL in C++
- Error/Exception Handling: C don’t support exception handling while C++ has try, catch, throw
- Function and Operator overloading: C don’t support, and C++ supports.
- Namespace support: All global identifier share same scope in C but not in C++ as namespace exists.
- Memory Management: C support manual memory management using malloc and free, while C++ include the manual as well as new, delete and constructor/destructor and smart pointers to handle memory.
- Reference Variables: C uses pointer to call by reference, C++ uses reference variables
- Default function argument values: C don’t support and C++ support default arguments values
- inline functions: inline functions exist in both C and C++ but mostly C uses macros and C++ encourages use of inline function
- Input output mechanism: C uses stdio.h functions printf() and scanf(), while C++ uses iostream with std::in and std::out.
Not much significant:
- Const behavior: const values can’t be used as array sizes in C but can be used as array size in C++.
- bool: There is no native bool type in traditional C, uses 0 for false and non-zero for true. C++ has native bool type with values true as 1 and false as 0.
Question 2: What is a pointer in C++? How is it different from a reference?
Answer: A pointer is a variable that stores the memory address of another variable. It “points to” the location of the data rather than holding the data itself. Pointers are a fundamental feature inherited from C and are widely used for dynamic memory management, passing large data efficiently, and working with low-level operations.
Key Differences:
| Aspect | Pointer | Reference | 
|---|---|---|
| Syntax | Uses * for declaration and dereferencing (e.g., int* ptr;, *ptr = 5;). | Uses & in declaration (e.g., int& ref = x;), no special operator to access. | 
| Memory Address | Explicitly stores the address of a variable (e.g., ptr = &x;). | Does not store an address; it’s an alias for the variable itself. | 
| Nullability | Can be nullptr (or NULL), meaning it doesn’t point to anything. | Cannot be null; must always refer to an existing variable. | 
| Reassignment | Can be reassigned to point to a different variable (e.g., ptr = &y;). | Cannot be reassigned; it’s bound to one variable for its lifetime. | 
| Initialization | Can be uninitialized (though risky, leading to undefined behavior). | Must be initialized at declaration (e.g., int& ref = x;). | 
| Usage Simplicity | Requires dereferencing (*) to access the value, more verbose. | Acts like the original variable no dereferencing needed. | 
| Dynamic Memory | Used with new/delete for heap allocation. | Cannot be used to manage dynamic memory directly. | 
| Pointer Arithmetic | Supports arithmetic (e.g., ptr++ to move to the next memory location). | Not applicable; references don’t support arithmetic. | 
| Pass-by Mechanism | Passed by value (the pointer itself) or used for pass-by-reference semantics. | Commonly used for pass-by-reference in functions (e.g., void func(int& x)) | 
Question 3: Explain the concept of constructor and destructor in C++.
Answer:
Constructor
- What: Special function to initialize an object when created.
- Name: Same as class (e.g., ClassName()), no return type.
- Types: Default (no args), parameterized (with args), copy (copies another object).
- Example: Class() { x = 0; } sets initial state.
Destructor
- What: Special function to clean up resources when an object is destroyed.
- Name: ~ClassName(), no return type or parameters.
- When: Called automatically when object goes out of scope or is deleted.
- Example: ~Class() { delete ptr; } frees memory.
Key Differences
- Constructor initializes; destructor cleans up.
- Constructor can have parameters; destructor cannot.
- Constructor called at creation; destructor at destruction.
Question 4: What is the purpose of the virtual keyword in C++?
Answer: virtual keyword has two functions, enabling polymorphism in inheritance and allowing virtual destructors for proper cleanup.
- Inheritance: If a function is defined as virtual in base class the derived class object referenced by base class pointer invokes the derived class function which override the base class function.
- Virtual Destructor: If base class destructor is declared virtual, then on call of destructor, first the derived class destructor is called then base class destructor is called.
Question 5: What are the differences between new and malloc in C++?
Answer: In C++, new and malloc both allocate memory dynamically on the heap, but they differ significantly in functionality and usage. Here’s a concise comparison:
| Aspect | new | malloc | 
|---|---|---|
| Type | C++ operator | C library function ( stdlib.h) | 
| Memory Allocation | Allocates memory and returns a typed pointer (e.g., int*). | Allocates raw memory and returns void*(requires casting). | 
| Constructor Call | Automatically calls the constructor for objects (e.g., classes). | Does not call constructors; only allocates memory. | 
| Size Calculation | Automatically calculates size based on type (e.g., new int). | Requires manual size specification (e.g., malloc(sizeof(int))). | 
| Deallocation | Uses deleteto free memory and call the destructor. | Uses freeto free memory, no destructor call. | 
| Exception Handling | Throws std::bad_allocon failure (can be caught). | Returns NULLon failure (must check manually). | 
| Initialization | Can initialize (e.g., new int(5)). | No initialization: memory is uninitialized. | 
Key Differences:
- newis C++-specific, object-aware (calls constructors/destructors), and type-safe.
- mallocis C-style, raw memory allocation without object support.
In C++, new is preferred for its safety and integration with object-oriented features, while malloc is rarely used unless interfacing with C code.
Question 6: What is the difference between struct and class in C++?
Answer: In C++, both struct and class define user-defined types that can hold data members and member functions, but they differ primarily in their default access specifiers and intended use. Here’s a concise comparison:
| Aspect | struct | class | 
|---|---|---|
| Default Access | public (members are accessible by default). | private (members are inaccessible by default). | 
| Inheritance | Default inheritance is public. | Default inheritance is private. | 
| Purpose | Typically used for simple data aggregates (POD-like types). | Used for complex objects with encapsulation and behavior. | 
| Syntax | struct Name { … }; | class Name { … }; | 
| Functionality | Can have constructors, destructors, methods, etc. (same as class). | Same as struct—no functional difference beyond access. | 
Question 7: What is constexpr in C++? How is it different from const?
Answer: In C++, constexpr and const both relate to constants, but they serve different purposes and operate at different stages of the program lifecycle. Here’s a concise explanation:
constexpr
Introduced: C++11, expanded in later standards (e.g., C++14, C++20).
What: Specifies that an expression, variable, or function can be evaluated at compile time, producing a constant result.
Purpose: Enables compile-time computation for performance optimization and ensures values are known before runtime.
Usage:
Variables: Must be initialized with a compile-time constant.
Functions: Must be evaluable at compile time if called in a constexpr context.
const
- What: Specifies that a variable’s value cannot be modified after initialization, but it doesn’t guarantee compile-time evaluation.
- Purpose: Enforces immutability at runtime or compile time, depending on context.
- Usage: Applies to variables; doesn’t inherently imply compile-time computation.
- Introduced: Original C++ (inherited from C).
Key Differences
| Aspect | constexpr | const | 
|---|---|---|
| Evaluation Time | Must be computable at compile time. | Can be set at runtime or compile time. | 
| Purpose | Compile-time constants/performance. | Immutability (no modification). | 
| Scope | Variables, functions, expressions. | Variables only. | 
| Initialization | Requires compile-time constant. | Can use runtime values. | 
| Example Use | constexpr int n = 10 * 2; (compile-time: 20) | const int n = y; (runtime if y is runtime). | 
Question 8: What is the difference between deep copy and shallow copy in C++?
Answer: In C++, deep copy and shallow copy refer to how objects are duplicated, particularly when they contain pointers or dynamically allocated memory. Here’s a concise comparison:
Shallow Copy
- What: Copies the values of an object’s members, including pointers, but does not duplicate the data they point to—both objects share the same memory.
- How: Default behavior of the assignment operator (=) or a simple copy constructor.
- Risk: Modifying one object’s data affects the other (shared resource), and double deletion can cause undefined behavior.
- Example:
  class Shallow {
  public:
      int* ptr;
      Shallow(int val) { ptr = new int(val); }
      // Default copy constructor (shallow)
  };
  Shallow s1(5);
  Shallow s2 = s1;  // Shallow copy: s2.ptr points to same memory as s1.ptr
Deep Copy
- What: Creates a fully independent copy of an object, duplicating both the object’s members and the data pointed to by pointers.
- How: Requires a custom copy constructor or assignment operator to allocate new memory and copy the data.
- Benefit: Each object has its own copy of the data, avoiding shared resource issues.
- Example:
  class Deep {
  public:
      int* ptr;
      Deep(int val) { ptr = new int(val); }
      // Custom copy constructor (deep)
      Deep(const Deep& other) { ptr = new int(*other.ptr); }
      ~Deep() { delete ptr; }
  };
  Deep d1(5);
  Deep d2 = d1;  // Deep copy: d2.ptr points to new memory with value 5
Key Differences
| Aspect | Shallow Copy | Deep Copy | 
|---|---|---|
| Memory Duplication | Copies pointers, not data. | Copies both pointers and data. | 
| Independence | Objects share data (coupled). | Objects are independent. | 
| Implementation | Default copy constructor/ =. | Custom copy constructor/ =. | 
| Performance | Faster (less memory allocation). | Slower (requires allocation). | 
| Risk | Shared data issues, memory errors. | Safe, no shared resource issues. | 
Example with Output:
#include <iostream>
class Example {
public:
    int* ptr;
    Example(int val) { ptr = new int(val); }
    // Shallow copy (default)
    // Example(const Example& other) { ptr = other.ptr; }
    // Deep copy
    Example(const Example& other) { ptr = new int(*other.ptr); }
    ~Example() { delete ptr; }
};
int main() {
    Example e1(10);
    Example e2 = e1;  // Change to shallow copy to see difference
    *e1.ptr = 20;     // With shallow: affects e2; with deep: only e1
    std::cout << *e1.ptr << " " << *e2.ptr << "\n";
    return 0;
}
- Shallow Output: 20 20(shared memory).
- Deep Output: 20 10(independent memory).
Summary
Deep Copy: Safe but costly; duplicates everything.
Use shallow for simple types, deep for objects with pointers or resources.
Shallow Copy: Quick but risky; copies pointers, not data.
Question 9: What are the different types of polymorphism in C++? Explain with examples.
Answer: In C++, polymorphism allows objects or functions to behave differently based on context. It’s a core feature of object-oriented programming and comes in several forms. Here are the main types:
1. Compile-Time Polymorphism (Static Polymorphism)
- What: Resolved at compile time using function or operator overloading or templates.
- Mechanism: The compiler determines which function or operation to use based on types and arguments.
- Types:
- Function Overloading: Multiple functions with the same name but different parameters.cpp void print(int x) { std::cout << x << "\n"; } void print(double x) { std::cout << x << "\n"; }
- Operator Overloading: Redefining operators for user-defined types.cpp class Point { public: int x; Point(int val) : x(val) {} Point operator+(Point& other) { return Point(x + other.x); } };
- Templates: Generic functions or classes that work with any type. template <typename T> T add(T a, T b) { return a + b; }
- Example:
  print(5);      // Calls int version
  print(5.5);    // Calls double version
  std::cout << add(3, 4) << "\n";  // Works with int
2. Run-Time Polymorphism (Dynamic Polymorphism)
- What: Resolved at runtime using inheritance and virtual functions.
- Mechanism: Uses a virtual table (vtable) to call the appropriate derived class function via a base class pointer or reference.
- Key Feature: Requires the virtualkeyword in the base class.
- Example:
  class Base {
  public:
      virtual void show() { std::cout << "Base\n"; }
      virtual ~Base() {}  // Virtual destructor
  };
  class Derived : public Base {
  public:
      void show() override { std::cout << "Derived\n"; }
  };
  int main() {
      Base* ptr = new Derived();
      ptr->show();  // Prints "Derived" (runtime decision)
      delete ptr;
      return 0;
  }
Summary of Differences
| Aspect | Compile-Time Polymorphism | Run-Time Polymorphism | 
|---|---|---|
| When Resolved | Compile time | Runtime | 
| Mechanism | Overloading, templates | Virtual functions, inheritance | 
| Performance | Faster (no runtime overhead) | Slower (vtable lookup) | 
| Flexibility | Fixed at compile time | Dynamic based on object type | 
| Keyword | None needed | virtualrequired | 
Other Notes
- Ad-hoc Polymorphism: Sometimes used to describe function/operator overloading specifically (a subset of compile-time polymorphism).
- Parametric Polymorphism: Another term for templates (also compile-time).
- C++ doesn’t natively support other forms like subtype polymorphism outside of virtual functions, but these two categories cover most use cases.
Polymorphism in C++ enhances flexibility: use compile-time for efficiency and simplicity, runtime for dynamic behavior in inheritance hierarchies.
 
        