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 delete to free memory and call the destructor. | Uses free to free memory, no destructor call. |
Exception Handling | Throws std::bad_alloc on failure (can be caught). | Returns NULL on failure (must check manually). |
Initialization | Can initialize (e.g., new int(5) ). | No initialization: memory is uninitialized. |
Key Differences:
new
is C++-specific, object-aware (calls constructors/destructors), and type-safe.malloc
is 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
virtual
keyword 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 | virtual required |
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.