0% found this document useful (0 votes)
4 views20 pages

C++ OOP Interview Questions (100 for Freshers)

The document provides a comprehensive list of C++ OOP interview questions and answers, covering key concepts such as encapsulation, abstraction, inheritance, and polymorphism. It includes conceptual explanations, coding examples, and debugging scenarios to illustrate the principles of object-oriented programming in C++. The content is structured to aid freshers in understanding and preparing for C++ OOP interviews.

Uploaded by

raj117557
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views20 pages

C++ OOP Interview Questions (100 for Freshers)

The document provides a comprehensive list of C++ OOP interview questions and answers, covering key concepts such as encapsulation, abstraction, inheritance, and polymorphism. It includes conceptual explanations, coding examples, and debugging scenarios to illustrate the principles of object-oriented programming in C++. The content is structured to aid freshers in understanding and preparing for C++ OOP interviews.

Uploaded by

raj117557
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

C++ OOP Interview Questions (100 for Freshers)

Encapsulation
• Conceptual: What is encapsulation in C++?
Answer: Encapsulation is the bundling of data (attributes) and functions (methods) into a single unit
(a class) and restricting access to the inner workings. It means that the internal representation of an
object is hidden from the outside, exposing only public interfaces. This provides controlled access to
the data 1 .
• Conceptual: How is encapsulation implemented in C++ and why is it useful?
Answer: In C++, encapsulation is achieved using classes with access specifiers ( public ,
protected , private ). By making class data members private (and providing public getter/setter
methods), you hide implementation details and prevent unauthorized access 1 . This improves
modularity and security, as changes to data representation won’t affect external code, and it makes
maintenance easier 2 3 .
• Conceptual: What is data hiding, and how does it differ from encapsulation?
Answer: Data hiding refers to restricting direct access to object data (often by marking it private
or protected ). Encapsulation is the broader concept of wrapping data and methods together.
Encapsulation facilitates data hiding by using access specifiers, but data hiding specifically focuses
on preventing unauthorized access to members 4 1 . In short, data hiding is a result of
encapsulation.
• Conceptual: How do you achieve data hiding in C++?
Answer: You declare class members as private (or protected ) so they cannot be accessed
directly from outside the class. Then you provide public member functions (getters/setters) to
allow controlled access. For example, a private variable can only be manipulated via its public
methods 5 1 .
• Conceptual: What are the advantages of encapsulation?
Answer: Encapsulation offers modularity (organizing code into self-contained classes),
maintainability, and security. By hiding internal data, you ensure data integrity and prevent
unauthorized modifications. It also makes code easier to maintain and extend, since implementation
details can change without affecting external code 2 .
• Coding: Write a simple C++ class Person with private members name and age , and public
methods to set and get these values (showing encapsulation).
Answer/Hints: Use a class with private: data members and public: setter/getter methods.
For example:

class Person {
private:
std::string name;
int age;
public:
void setName(const std::string &n) { name = n; }
std::string getName() const { return name; }

1
void setAge(int a) { age = a; }
int getAge() const { return age; }
};

• Output-Based: Consider the code:

class A { private: int x = 5; };


int main() {
A a;
std::cout << a.x;
return 0;
}

What is the output or error?


Answer: This code will fail to compile. The private member x is not accessible outside class A .
You’ll get an error like “ int A::x is private within this context” 5 .
• Debugging: What is wrong with the following code? How would you fix it?

class Box {
double width;
public:
Box(double w) { width = w; }
};
int main() {
Box b(5.0);
std::cout << b.width;
}

Answer: The data member width is private by default (since no access specifier is given inside the
class). It cannot be accessed from main . To fix, either declare width as public , or better,
provide a public getter method (e.g., double getWidth() const { return width; } ). This
upholds encapsulation 6 5 .

Abstraction
• Conceptual: What is abstraction in C++?
Answer: Abstraction is the concept of exposing only the necessary features of an object or module
while hiding the implementation details. It means showing a high-level interface and hiding low-level
complexity. For example, a car’s accelerator abstracts away the complex engine mechanics – you
only press it to increase speed. In code, abstraction is achieved using abstract classes and interfaces.
You present only what is needed to the user 7 .
• Conceptual: How do classes and pure virtual functions support abstraction?
Answer: In C++, an abstract class (one with at least one pure virtual function) defines an interface
without specifying full implementation. A pure virtual function ( virtual void f() = 0; ) forces
derived classes to implement it. This allows you to define “what” an object should do (interface) but

2
not “how” it does it. Users of the class rely on the interface and don’t need to know the underlying
details.
• Conceptual: What is the difference between abstraction and encapsulation?
Answer: Abstraction focuses on exposing relevant interfaces and hiding implementation complexity
7 , whereas encapsulation bundles data and methods into a class and uses access control to hide

data 8 7 . In short, abstraction is about what a class can do (interface), while encapsulation is
about how it is implemented (hiding data).
• Conceptual: What is an abstract class in C++? How do you declare one?
Answer: An abstract class is a class that cannot be instantiated on its own because it has one or
more pure virtual functions. You declare a method as pure virtual by assigning = 0 in its
declaration (e.g., virtual void draw() = 0; ). For example:

class Shape {
public:
virtual void draw() = 0; // pure virtual
};

Shape is abstract; only a derived class that overrides draw() can be instantiated.
• Coding: Define an abstract class Animal with a pure virtual function makeSound() . Then define
a subclass Dog that implements makeSound() , and demonstrate calling it.
Answer/Hints:

class Animal {
public:
virtual void makeSound() = 0; // pure virtual (abstract)
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Bark\n";
}
};
int main() {
Dog d;
d.makeSound(); // prints "Bark"
return 0;
}

Here, Animal is abstract and cannot be instantiated. Dog provides the implementation for
makeSound() .
• Output-Based: What happens if you try to instantiate an abstract class?
Answer: The code will fail to compile. If a class has a pure virtual function, it cannot be instantiated.
For example:

3
class A { virtual void f() = 0; };
A a;

This gives a compile-time error like “cannot declare variable ‘a’ to be of abstract type ‘A’.” You must
define all pure virtual functions in a derived class before instantiating 9 .
• Debugging: The following code does not compile. Why?

class Base { virtual void show() = 0; };


class Derived : public Base { };
int main() {
Derived d;
d.show();
return 0;
}

Answer: Derived does not override the pure virtual function show() from Base , so Derived
is still abstract. You must provide an implementation for show() in Derived before you can
create an object of Derived . Adding void show() override { ... } to Derived would fix
it.

Inheritance
• Conceptual: What is inheritance in C++?
Answer: Inheritance allows a class (derived class) to inherit properties (data members) and
behaviors (methods) from another class (base class). It promotes code reuse by enabling a new class
to use existing class code. For example, class Car : public Vehicle means Car inherits
from Vehicle . Inheritance is a fundamental OOP feature in C++ 10 .
• Conceptual: What are the types of inheritance supported in C++? Give examples.
Answer: C++ supports several inheritance types:
• Single Inheritance: One base, one derived (e.g., class Car : public Vehicle ).
• Multilevel Inheritance: A derived class becomes base for another (e.g., class C inherits from
B , and B inherits from A ).
• Multiple Inheritance: One class inherits from more than one base (e.g.,
class Hybrid : public Flying, public Swimming ).
• Hierarchical Inheritance: One base class, multiple derived classes (e.g., class Car : public
Vehicle; class Boat : public Vehicle ).
• Hybrid (Multipath) Inheritance: Combination of two or more (like multiple + multilevel). Multipath
(diamond problem) is a special hybrid case where ambiguity can arise 11 .
• Conceptual: In C++, which base class members are accessible in the derived class?
Answer: A derived class can directly access the public and protected members of its base
class. Private members of the base class are not directly accessible by the derived class (you’d need
getter/setter or make the derived class a friend to access them) 12 . For example, if Parent has
a private id_p , Child cannot directly access id_p ; protected and public members are inherited
as usual 12 .

4
• Conceptual: What is the difference between public, protected, and private inheritance?
Answer: This controls how base class members’ access levels are treated in the derived class:
• Public inheritance: Public and protected members of base remain public and protected in the
derived class.
• Protected inheritance: Public and protected base members become protected in derived.
• Private inheritance: Public and protected base members become private in derived.
(In all cases, private base members are inaccessible in the derived class 12 .)
• Conceptual: What is the “diamond problem” in multiple inheritance and how can C++ resolve it?
Answer: The diamond problem occurs in multiple inheritance when two base classes inherit from a
common ancestor, and a derived class inherits from both. This creates ambiguity because the top
ancestor’s members appear twice. C++ resolves this using virtual inheritance. Declaring inheritance as
virtual (e.g., class B : virtual public A ) ensures there is only one shared base A ,
avoiding duplicate subobjects 11 .
• Coding: Given classes
class A { public: int x; }; class B : public A { }; class C : public A { };
class D : public B, public C { }; write code to resolve ambiguity when accessing x from
D .
Answer/Hints: Without virtual inheritance, D has two A subobjects, so d.x is ambiguous. Use
virtual inheritance:

class B : virtual public A { };


class C : virtual public A { };
class D : public B, public C { };

Now D has one A and d.x refers unambiguously.


• Output-Based: What is the output of this code?

#include <iostream>
using namespace std;
class Parent { public: int id_p = 5; };
class Child : public Parent { public: int id_c = 10; };
int main() {
Child obj;
cout << obj.id_p << " " << obj.id_c;
return 0;
}

Answer: 5 10 – The derived class Child inherits id_p from Parent (public inheritance), so
obj.id_p is accessible and prints 5 . Then obj.id_c prints 10 13 .
• Debugging: Why does the following code cause a compiler error?

class Base { private: int val; };


class Derived : public Base {
public:

5
void setVal(int x) { val = x; }
};

Answer: val is a private member of Base , so Derived cannot access it directly. The line
val = x; is invalid because val is not accessible. To fix, make val protected or provide a
protected/public setter in Base .

Polymorphism (Compile-Time)
• Conceptual: What is compile-time (static) polymorphism? How is it achieved in C++?
Answer: Compile-time polymorphism (also called static binding) is when the compiler decides which
function or operator to invoke at compile time. In C++, this is achieved via function overloading and
operator overloading. That means having multiple functions with the same name but different
signatures, or redefining operators for user-defined types 14 .
• Conceptual: Explain function overloading with an example.
Answer: Function overloading lets you have multiple functions with the same name but different
parameter lists. The compiler chooses which function to call based on arguments. For example:

void add(int a, int b) { cout << "Int sum = " << a+b; }
void add(double a, double b) { cout << "Float sum = " << a+b; }

Here, add(10,2) calls the first, and add(5.3, 6.2) calls the second 15 16 .
• Conceptual: Explain operator overloading in C++.
Answer: Operator overloading allows defining custom behavior for operators with user-defined
types. For instance, you can overload operator+ for a Complex class so you can write c1 +
c2 . The overloaded operator is implemented as a special function. For example:

Complex operator+(const Complex &a) {


return Complex(real + a.real, imag + a.imag);
}

This lets you use c1 + c2 with Complex objects 17 18 .


• Coding: Write a class Complex with real and imag members and overload the + operator to
add two complex numbers.
Answer/Hints:

class Complex {
public:
double real, imag;
Complex(double r=0, double i=0): real(r), imag(i) {}
Complex operator+(const Complex &o) const {
return Complex(real + o.real, imag + o.imag);
}
};
int main() {

6
Complex c1(1,2), c2(3,4);
Complex c3 = c1 + c2;
cout << c3.real << "+" << c3.imag << "i"; // 4+6i
}

• Conceptual: Which operators cannot be overloaded in C++? (Name a few).


Answer: Certain operators are not overloadable in C++: the scope resolution operator :: , ternary
operator ?: , member access or dot operator . , pointer-to-member operators .* and ->* ,
and also sizeof , and the type-casting operators ( dynamic_cast , static_cast ,
const_cast , reinterpret_cast ) 19 . All other operators (arithmetic, logical, [] , () , etc.)
can be overloaded.
• Conceptual: What are the differences between function overloading and function overriding?
Answer: Function overloading (compile-time polymorphism) is having multiple functions with the
same name but different signatures in the same scope 20 . Function overriding (runtime
polymorphism) is redefining a base class’s virtual function in a derived class 21 . Overloading is
resolved at compile time, overriding (with virtual ) is resolved at runtime.
• Output-Based: What is the output of the following code?

#include <iostream>
using namespace std;
class Test {
public:
int x;
Test(int x): x(x) {}
Test operator+(const Test &t) {
return Test(x + t.x);
}
};
int main() {
Test a(10), b(20);
Test c = a + b;
cout << c.x;
}

Answer: 30 – The + operator is overloaded to add the x values of a and b . The line
Test c = a + b; creates c with x = 10+20 , so printing c.x outputs 30 22 .
• Debugging: Why does this function overloading code not compile?

void fun(int a, float b);


void fun(int x, int y);
...
fun(10, 20);

Answer: The call fun(10,20) is ambiguous here because both fun(int,float) and
fun(int,int) can match (20 can convert to either float or int ). The compiler cannot decide

7
which overload to call. To fix it, ensure the call matches exactly one overload or use a cast (e.g.,
fun(10,20.0f) for the first or fun(10,int(20)) ).

Polymorphism (Runtime)
• Conceptual: What is runtime (dynamic) polymorphism in C++?
Answer: Runtime polymorphism (late binding) is when the decision of which function to call is made
at run time. In C++, this is achieved through virtual functions and function overriding. A base class
pointer or reference can call derived class methods if they override a virtual function 23 .
• Conceptual: What is a virtual function?
Answer: A virtual function is a member function declared in a base class with the virtual
keyword, intended to be overridden in derived classes 24 . It tells the compiler to use dynamic
binding for calls through base pointers. When you invoke a virtual function on a base pointer
referring to a derived object, the derived class’s version is called 25 24 .
• Coding: Demonstrate runtime polymorphism with an example using a base class pointer.
Answer/Hints:

class Base {
public:
virtual void show() { std::cout << "Base\n"; }
virtual ~Base() = default;
};
class Derived : public Base {
public:
void show() override { std::cout << "Derived\n"; }
};
int main() {
Base *b = new Derived();
b->show(); // Prints "Derived"
delete b;
}

Since show() is virtual, b->show() calls Derived::show() at runtime 25 .


• Conceptual: Explain the difference between overriding and overloading.
Answer: Overriding is redefining a base class’s virtual function in a derived class (same signature)
21 , enabling runtime polymorphism. Overloading is having multiple functions with same name but

different signatures in the same scope, enabling compile-time polymorphism 20 .


• Conceptual: What is a pure virtual function? How is it declared?
Answer: A pure virtual function is a virtual function declared with = 0 in the base class, making the
class abstract. For example: virtual void f() = 0; . It has no implementation in the base, and
derived classes must override it.
• Coding/Output: What does this code output and why?

#include <iostream>
using namespace std;
class Base {

8
public:
virtual void print() { cout << "Base"; }
};
class Derived : public Base {
public:
void print() override { cout << "Derived"; }
};
int main() {
Base *bp = new Derived();
bp->print();
delete bp;
return 0;
}

Answer: It prints Derived . The pointer bp is of type Base* but points to a Derived object.
Because print() is virtual, the Derived version is called at runtime 25 .
• Debugging: What is wrong with calling a non-virtual method through a base pointer? Example:

class A { public: void f() { cout << "A"; } };


class B : public A { public: void f() { cout << "B"; } };
int main() {
A *p = new B();
p->f();
}

Answer: Since f() is not virtual, the call p->f() uses static binding to A::f() . It will print A
instead of B . This is often surprising – to enable polymorphism, f() should be declared
virtual in A . Otherwise you always get the base class version.

Constructors and Destructors


• Conceptual: What is a constructor in C++? How is it different from other functions?
Answer: A constructor is a special member function with the same name as its class, called
automatically when an object is created. It has no return type (not even void ) 26 . Its purpose is to
initialize the object’s data members. For example, class C { public: C() { /* ... */ } };
defines a default constructor. It’s invoked when you declare C obj; .
• Conceptual: What is a destructor in C++? When is it called?
Answer: A destructor is a special member function with the same name as the class prefixed by ~ ,
called automatically when an object’s lifetime ends (goes out of scope or is deleted) 27 . Its role is to
free resources (like memory or file handles) that the object may have acquired 28 . Example: ~C()
{ /* cleanup */ } .
• Conceptual: Can constructors and destructors be inherited?
Answer: No, constructors and destructors are not inherited by derived classes 29 . However, when a
derived class object is created, the base class constructor is called automatically (first base, then
derived) 29 . Similarly, upon destruction, derived destructor runs before base destructor, in reverse
order 30 .

9
• Conceptual: What happens if you don’t declare any constructor or destructor?
Answer: If you don’t provide them, C++ automatically generates a default constructor (that does
default member initialization) and a default destructor (that does member destruction) 31 26 . Also,
the compiler provides a default copy constructor and copy-assignment operator for shallow copying
(member-wise copy) 31 .
• Debugging: Why might the default copy constructor lead to problems?
Answer: The implicit copy constructor performs a shallow copy of all members 31 . If a class holds
resources like raw pointers, both the original and copy end up pointing to the same memory. This
can cause double-free or resource leaks. In such cases you need to define a custom copy constructor
(and assignment operator) to perform a deep copy or to disable copying.
• Conceptual: What is the copy constructor? When is it called?
Answer: A copy constructor initializes an object using another object of the same class 32 . It has
the form ClassName(const ClassName &other) . It is called when a new object is created from
an existing object, e.g., ClassB b = a; or when passing/returning objects by value 32 33 .
• Conceptual: What is the difference between copy constructor and copy assignment operator?
Answer: The copy constructor creates a new object as a copy of an existing one. The assignment
operator ( operator= ) copies data into an already-initialized object. In short, ClassB b = a;
invokes the copy constructor, while b = a; (after b is already created) invokes the assignment
operator 33 . The copy constructor allocates a fresh object (with its own storage); the assignment
operator may need to clean up old data before copying into the existing object 33 .
• Conceptual: What is a default constructor? When does the compiler provide one?
Answer: A default constructor is one that can be called with no arguments (either provided by user
or the compiler). If you do not define any constructors, the compiler generates a default (no-
argument) constructor for you, which default-initializes members 31 . However, if you define any
constructor (with or without arguments), the compiler does not generate the default one
automatically.
• Output-Based: What is the output of this code?

#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor\n"; }
~A() { cout << "A dtor\n"; }
};
int main() {
{
A obj;
}
cout << "Done";
return 0;
}

Answer: The output is:

10
A ctor
A dtor
Done

Explanation: Creating obj calls the constructor ( A ctor ). When the block ends, obj goes out of
scope and the destructor runs ( A dtor ). Finally, Done is printed. This shows constructors run on
creation and destructors on destruction 30 .
• Conceptual: What is a static object and when is its destructor called?
Answer: A static object (global variable or static local) persists for the life of the program. Its
destructor is called once when the program ends (after main exits) 30 .

Access Specifiers
• Conceptual: What are the access specifiers in C++ and what do they mean?
Answer: C++ has three access specifiers for class members:
• public : members are accessible from any part of the program 3 .
• protected : like private but accessible in derived classes 34 .
• private : members are accessible only within the class itself (or friend functions/classes) 5 . By
default, class members are private if no specifier is given; in a struct , default is public 35 .
• Conceptual: What is the default access level for class and struct members in C++?
Answer: In a class , the default access for members is private (if no public: , protected: ,
etc. is given) 35 . In a struct , the default access is public. For example, class X { int a; };
means a is private by default.
• Conceptual: Can a protected member be accessed outside the class?
Answer: A protected member cannot be accessed by non-member functions or classes outside.
It can only be accessed within its own class and by classes derived from it 34 . It is not accessible in
unrelated classes.
• Conceptual: Explain friend functions/classes in context of access control.
Answer: A friend function or friend class is granted access to the private/protected members of the
class in which it is declared as a friend 36 37 . Declaring a function or class friend inside a class
means that function/class can access all private/protected members. However, friendship is not
inherited or reciprocal: if A declares B as friend, B can access A 's private members, but A
cannot access B ’s, and derived classes of A are not automatically friends of B 36 38 .
• Conceptual: If class B is a friend of class A , is B also a friend of A ’s derived classes?
Answer: No. Friend relationships are not inherited. If class A declares B as a friend, B can
access private members of A , but not private members of any class derived from A 38 .
• Debugging: Why does this code give an access error?

class Base {
private:
int data;
public:
friend class FriendClass;
};
class Derived : public Base {

11
void foo() { data = 10; }
};

Answer: Even though FriendClass is a friend of Base , this friendship is not inherited by
Derived . In Derived::foo() , data is private in Base and not accessible. Making data
protected or providing a setter in Base would fix it.

Virtual Functions and Vtables


• Conceptual: What is a virtual table (vtable) in C++?
Answer: A vtable is a compiler-generated table of function pointers used to implement dynamic
dispatch of virtual functions 24 . Each class with virtual functions has its own vtable. Entries in the
vtable point to the “most derived” implementation of each virtual function. At runtime, the object’s
hidden pointer (vptr) points to the correct vtable so the appropriate function is called 24 .
• Conceptual: What is a vptr (virtual pointer)?
Answer: A vptr (virtual pointer) is a hidden pointer inserted by the compiler into objects of classes
with virtual functions 39 . It points to the class’s vtable. Every object of a class with virtual functions
has its own vptr. The vptr allows the program to look up which function implementation to call at
runtime. Importantly, vptrs and vtables are only created for classes with virtual functions 39 .
• Conceptual: When is a vptr created for a class?
Answer: A vptr is created if and only if a class has at least one virtual function (or inherits one).
Classes with no virtual functions have no vtable or vptr 39 .
• Conceptual: How many vtables are there in a program? And how many vptrs?
Answer: There is one vtable per class that has virtual functions 24 . Each object of such a class has
its own vptr (pointer to that class’s vtable) 39 . So many vptrs (one per object), but one shared vtable
per class.
• Conceptual: What is the effect of forgetting a virtual destructor in a base class when deleting a
derived object through a base pointer?
Answer: If the base class destructor is not virtual, deleting a derived-class object via a base pointer
will only call the base destructor. The derived destructor won’t run, leading to resource leaks. For
example, if Base* b = new Derived(); delete b; , only Base::~Base() runs if it’s non-
virtual. Declaring the base destructor virtual ensures the derived destructor is called too 40 41 .
• Conceptual: What is a pure virtual destructor, and can you have one?
Answer: You can declare a destructor as pure virtual ( virtual ~A() = 0; ) to make a class
abstract, but you must still provide an implementation (even if empty). The destructor will be called
in reverse order during cleanup. Pure virtual destructors are a rare advanced case; usually, you
simply mark the destructor virtual if needed.
• Conceptual: How does the compiler find the correct function to call for a virtual function?
Answer: When a virtual function is called on an object (via pointer/reference), the program uses the
object’s vptr to look up the function address in the vtable, then invokes that function. This decision is
made at runtime (dynamic binding) based on the actual object type 24 .
• Debugging: Given:

class A { public: virtual void f() { cout<<"A"; } };


class B : public A { public: virtual void f(int) { cout<<"B"; } };

12
A *p = new B();
p->f();

Why does this not call B’s f(int) ?


Answer: In C++, f(int) in B hides A ’s f() , it does not override it because the signature is
different (overloading vs overriding). Because A::f() is virtual, p->f() resolves to A::f()
(not overloaded by B ). To override, B must declare void f() override . This is a common
mistake where overloading a virtual function does not override it; it simply adds a new function in
B .

Friend Functions and Classes


• Conceptual: What is a friend function in C++? How is it declared?
Answer: A friend function is a non-member function that is granted access to private and protected
members of a class. It is declared inside the class with the friend keyword (but defined outside).
For example:

class A {
int x;
friend void showX(A &a);
};
void showX(A &a) { cout << a.x; } // can access private x

showX can access A ’s private members because it is a friend 37 .


• Conceptual: What is a friend class in C++?
Answer: A friend class is a class whose member functions have access to the private and protected
members of another class that declares it as friend. For example:

class B;
class A {
private: int x;
friend class B;
};
class B {
public:
void foo(A &a) { cout << a.x; }
};

Here, B is declared a friend of A , so B::foo can access A::x 36 . Friendship is one-way: A ’s


members can access B only if B is also declared a friend of A .
• Conceptual: Can friend functions be inherited by derived classes?
Answer: No. Friends are not inherited. If class B is a friend of A , it has special access only to A ’s
members. A derived class of A is not automatically a friend to B . Likewise, a friend of A does not
become a friend of A ’s derived classes 38 .

13
• Conceptual: Where in a class definition can friend be declared? Does it matter if it’s under
public , protected , or private ?
Answer: You can declare a friend function or class in any section of the class ( public: ,
private: , or protected: ), and it makes no difference. The friendship grant applies regardless
of where you put the friend declaration 42 .
• Debugging: Why is this code illegal?

class X {
friend void f();
int data;
};
void f() { cout << data; }

Answer: f() is not a member of class X , it’s a global function. Inside f() , the name data is
undefined because data is not a global variable. The correct way to use the friend function is:

void f() {
X obj;
cout << obj.data;
}

where f accesses data through an X instance (allowed because f is a friend of X ).

Operator Overloading
• Conceptual: What is operator overloading? Why would you use it?
Answer: Operator overloading lets you define custom behavior for C++ operators (like + , - , == ,
<< , etc.) when applied to user-defined types. It makes classes more intuitive to use (e.g., adding
two Complex objects with c1 + c2 ). You overload operators by defining special functions
( operator+ , operator<< , etc.) either as member or friend functions. For example, to overload
== , you might write bool operator==(const MyClass &a, const MyClass &b) .
• Conceptual: Can every operator be overloaded? Name some that cannot.
Answer: No, not all operators are overloadable. You cannot overload: :: (scope resolution), ?:
(ternary), . (dot member access), .* (pointer-to-member), sizeof , and all casting operators
( static_cast , etc.) 19 . All other operators (arithmetic, comparison, [] , () , -> , etc.) can be
overloaded.
• Conceptual: How do you overload << and >> for a custom class? Why are they often non-
member (friend) functions?
Answer: To overload input/output operators, you typically write them as friend non-member
functions so the stream object is on the left. For example:

class Point { int x,y; public:


friend std::ostream& operator<<(std::ostream &out, const Point &p) {
return out << "(" << p.x << "," << p.y << ")";

14
}
};

This allows std::cout << pointObj; . They are often friends because the left operand
( ostream ) is not a member of Point .
• Coding: Overload the assignment operator ( = ) for a simple class MyString that manages a
char* . What special care must you take?
Answer/Hints: You should check for self-assignment and clean up old memory before copying. For
example:

class MyString {
private:
char *str;
public:
MyString(const char *s=“”) { str = new char[strlen(s)+1];
strcpy(str,s); }
~MyString() { delete[] str; }
MyString& operator=(const MyString &other) {
if (this != &other) { // avoid self-assign
delete[] str; // free old memory
str = new char[strlen(other.str)+1];
strcpy(str, other.str);
}
return *this;
}
};

• Debugging: Why is it wrong to overload the operator= as void operator=(const MyClass


&other) instead of returning a reference?
Answer: The standard signature for assignment operator is MyClass& operator=(const
MyClass &other) . It should return *this by reference to allow chaining assignments (e.g.,
a = b = c; ). If you make it void , you cannot chain, and it also breaks the usual semantics.

Templates
• Conceptual: What are templates in C++?
Answer: Templates support generic programming. A template allows writing code that works with
any data type by parameterizing the type. For example, a function template template<typename
T> T max(T a, T b) can compute the max of ints, doubles, etc. Similarly, class templates let you
define container classes (like vector<T> ) that work for any T 43 . Templates avoid code
duplication.
• Conceptual: What is the difference between a function template and a class template?
Answer: A function template defines a family of functions for different data types. You write it with
template<typename T> before the function, and the compiler generates versions for the types
you use 43 . A class template similarly defines a family of classes. For example,

15
template<typename T>
class Pair { T first, second; };

You can then instantiate Pair<int> or Pair<double> .


• Coding: Write a function template to swap two values of any type.
Answer/Hints:

template <typename T>


void swapValues(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x=5, y=10;
swapValues(x,y); // swaps ints
std::string s1="a", s2="b";
swapValues(s1,s2); // swaps strings
}

• Conceptual: What is template specialization? (Briefly)


Answer: Template specialization allows you to provide a custom implementation of a template for a
specific type. For example, you can specialize template<> void func<char>(char* s)
{ ... } if you need a different behavior when T is char . (Full and partial specializations are
advanced, but often seen in interviews.)
• Debugging: The following code gives an error. What’s wrong?

template <class T>


class MyClass {
T data;
MyClass() { } // constructor
~MyClass() { } // destructor
};

Answer: The constructor MyClass() is declared private by default (because no access specifier
is given in the class template). This means you cannot create objects of MyClass<T> . You should
add public: before the constructor and destructor.

Exception Handling
• Conceptual: What is an exception in C++? How do you handle exceptions?
Answer: An exception is a runtime error or unexpected condition (e.g., divide by zero) that can
disrupt normal flow. In C++, you handle exceptions using try , throw , and catch blocks 44 .
You put code that might fail in a try block. To signal an error, use throw (e.g., throw

16
std::runtime_error("error") ). Then you catch the exception type in a catch(...) block
to handle it and keep the program running gracefully 44 45 .
• Conceptual: How do you throw and catch exceptions? What types can be thrown?
Answer: Use throw followed by a value or object: e.g., throw 42; or throw
MyException("msg"); . C++ allows throwing any type: built-in (like int ), std::exception -
derived, or user-defined objects 45 . Catch with catch(Type e) { ... } , matching the type.
Common practice is to throw/ catch objects derived from std::exception because they can carry
error messages via what() 46 .
• Conceptual: What is stack unwinding? What happens to local objects when an exception is thrown?
Answer: Stack unwinding is the process of destroying local objects when control exits blocks (either
normally or due to an exception) 47 . If an exception is thrown, C++ unwinds the stack: it destroys all
objects with automatic storage in reverse order of construction as it searches for a matching
catch 47 48 . This ensures proper cleanup (calling destructors) even in error cases.
• Conceptual: Is there a finally block in C++? How do you ensure cleanup?
Answer: C++ does not have a finally keyword. Cleanup is usually done by RAII (destructors) or
by catching exceptions and rethrowing if needed. You can also use catch-all ( catch(...) ) to
perform final actions before rethrowing. The destructor of local objects will always be called during
stack unwinding, ensuring cleanup even without finally .
• Conceptual: What is std::exception and its what() method?
Answer: std::exception is the base class for standard exceptions (in <stdexcept> ). Its
method what() returns a C-string describing the exception. Many library functions throw
exceptions derived from std::exception (like std::out_of_range ). Using
catch(std::exception &e) , you can call e.what() to get an error message 46 .
• Coding: Write code that throws a std::invalid_argument exception if a number is negative,
and catch it in main .
Answer/Hints:

#include <stdexcept>
void check(int x) {
if (x < 0) throw std::invalid_argument("Negative not allowed");
}
int main() {
try {
check(-5);
} catch (const std::invalid_argument &e) {
std::cout << "Error: " << e.what() << "\n";
}
}

This prints: Error: Negative not allowed . It demonstrates throwing and catching a standard
exception.
• Output-Based: What is the output of this code?

#include <iostream>
using namespace std;
void f() { throw 99; }

17
int main() {
try {
f();
cout << "After throw\n";
} catch (int x) {
cout << "Caught " << x << "\n";
}
return 0;
}

Answer:

Caught 99

Explanation: When f() throws 99 , control jumps to the catch(int x) , so "Caught 99" is
printed. The line "After throw" is never reached.
• Debugging: Why might catching exceptions by value cause slicing issues? (Hint: use references)
Answer: If you throw a derived exception class object and catch by a base class by value, the
derived part is sliced off. For example, throwing DerivedException and catching MyException
e copies only the MyException base part. To preserve full exception info, catch by reference
( catch(const MyException &e) ) 46 .

Object Lifecycle
• Conceptual: What is the order of constructor and destructor calls in inheritance?
Answer: When creating an object of a derived class, base class constructors are called first (in
inheritance chain order), then the derived class constructors 30 . On destruction, the opposite order
is followed: derived class destructor runs first, then base class destructor 30 . For example,
instantiating Derived calls Base ’s constructor before Derived ’s, and destroying Derived
calls its destructor before Base ’s 30 .
• Conceptual: What is a static local variable? When is it initialized and destroyed?
Answer: A static local (inside a function) or global object has static storage duration. It is
initialized only once (before the first use or program start, depending on C++ version) and destroyed
when the program ends. Its destructor runs after main exits 30 .
• Conceptual: What is a shallow copy vs. deep copy? When do you need a deep copy?
Answer: A shallow copy duplicates pointers and non-pointer members as-is (default copy behavior
31 ). A deep copy duplicates the pointed-to data as well. You need a deep copy when your class has

pointer members that own dynamic memory; otherwise, two objects would share the same memory
(leading to double-delete). In that case, implement a copy constructor/assignment that allocates new
memory and copies contents.
• Conceptual: What is RAII and why is it important?
Answer: Resource Acquisition Is Initialization (RAII) is a C++ idiom where resource allocation (like
memory, file handles) is tied to object lifetime. Resources are acquired in a constructor and released
in the destructor. This ensures resources are freed automatically when objects go out of scope, even
if exceptions occur, preventing leaks. Examples include smart pointers ( std::unique_ptr ) and
containers. (This principle ensures clean object lifecycle management.)

18
• Conceptual: Describe the lifecycle of a local object in a function.
Answer: A local (automatic) object is constructed when execution reaches its declaration. It remains
valid until the end of its scope (block or function). When the scope ends (normally or via exception),
the object’s destructor is called and its storage is freed 30 47 .
• Debugging: What happens if a constructor throws an exception? What should you be careful about?
Answer: If a constructor throws, the object is not created and its destructor will not run. However,
any fully constructed sub-objects (members, base) will have their destructors called (stack
unwinding) 47 . It’s important to ensure that any resources allocated before the throw are cleaned
up (e.g., use RAII) so you don’t leak.
• Conceptual: How are temporaries (rvalues) initialized and destroyed?
Answer: Temporary objects (rvalues) are typically created to hold function return values or when
passing by value. They are initialized as needed and then destroyed at the end of the full expression
(the semicolon or enclosing function call). The compiler can also optimize by eliding temporaries
(return value optimization) in many cases.
• Coding: Given:

class C {
public:
C() { std::cout<<"C ctor "; }
~C() { std::cout<<"C dtor "; }
};
C f() { return C(); }
int main() {
C obj = f();
return 0;
}

What is the output (assuming no copy elision)?


Answer: Likely:

C ctor C dtor C dtor

Explanation:
• f() creates a temporary C (“C ctor”).
• That temporary is returned, creating another C to initialize obj , then the temporary from f() is
destroyed (“C dtor”).
• At program end, obj is destroyed (“C dtor”). (Modern compilers may elide one or more of these,
but logically this is the sequence if no elision.)

Sources: General C++ OOP concepts and code examples 1 4 12 29 7 8 24 40 41 47

(GeeksforGeeks and other reliable references).

1 2 Encapsulation in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/encapsulation-in-cpp/

19
3 5 6 34 35 Access Modifiers in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/access-modifiers-in-c/

4 Difference Between Data Hiding and Encapsulation


https://www.tutorialspoint.com/difference-between-data-hiding-and-encapsulation

7 Abstraction in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/abstraction-in-cpp/

8 9 Difference between Abstraction and Encapsulation in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/difference-between-abstraction-and-encapsulation-in-c/

10 11 12 13 29 30 38 Inheritance in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/inheritance-in-c/

14 15 16 17 18 20 21 22 23 25 C++ Polymorphism | GeeksforGeeks


https://www.geeksforgeeks.org/cpp-polymorphism/

19 What are the Operators that Can be and Cannot be Overloaded in C++? | GeeksforGeeks
https://www.geeksforgeeks.org/what-are-the-operators-that-can-be-and-cannot-be-overloaded-in-cpp/

24 39 vTable And vPtr in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/vtable-and-vptr-in-cpp/

26 27 28 C++ Interview questions based on constructors/ Destructors. | GeeksforGeeks


https://www.geeksforgeeks.org/c-interview-questions-based-on-constructors-destructors/

31 32 Copy Constructor in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/copy-constructor-in-cpp/

33 Copy Constructor vs Assignment Operator in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/copy-constructor-vs-assignment-operator-in-c/

36 37 42 Friend Class and Function in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/friend-class-function-cpp/

40 41 When to Use Virtual Destructors in C++? | GeeksforGeeks


https://www.geeksforgeeks.org/when-to-use-virtual-destructors-in-cpp/

43 Templates in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/templates-cpp/

44 45 46 Exception Handling in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/exception-handling-c/

47 48 Stack Unwinding in C++ | GeeksforGeeks


https://www.geeksforgeeks.org/stack-unwinding-in-c/

20

You might also like