Open In App

C++ OOP Interview Questions

Last Updated : 26 Aug, 2025
Comments
Improve
Suggest changes
3 Likes
Like
Report

C++ supports Object-Oriented Programming through features like classes, inheritance, polymorphism, and encapsulation. These concepts help build reusable, maintainable, and efficient code, which is why they are often a key focus in interviews.

1. What is the difference between struct and class?

structclass
Members are public by default.Members are private by default.
Public inheritance by defaultSupports inheritance (with public, protected, or private access).
Used for Plain Old Data (POD) structures, or simple data grouping.Suitable for complex objects that may include methods, constructors, and destructors.

Example:

C++
#include <iostream>
using namespace std;

struct MyStruct {
    int x;            // public by default
    void show() {
        cout << "Struct x = " << x << endl;
    }
};

class MyClass {
    int y;            // private by default
public:
    MyClass(int val) : y(val) {}   // constructor
    void show() {
        cout << "Class y = " << y << endl;
    }
};

int main() {
    MyStruct s; 
    s.x = 10;      // allowed (public by default)
    s.show();

    MyClass c(20);
    // c.y = 20;   // not allowed, y is private
    c.show();      // access via public function
}

2. What are the C++ access modifiers?

The access restriction specified to the class members (whether it is member function or data member) is known as access modifiers/specifiers. 

C++ provides three access modifiers:

  1. Private - It can neither be accessed nor be viewed from outside the class 
  2. Protected - It can be accessed if and only if the accessor is the derived class
  3. Public - It can be accessed or be viewed from outside the class 

Example:

C++
#include <iostream>
using namespace std;

class Demo {
private:
    int a = 1;      // Not accessible outside class

protected:
    int b = 2;      // Accessible in derived class

public:
    int c = 3;      // Accessible from anywhere

    void show() {
        cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
    }
};

class Derived : public Demo {
public:
    void access() {
        // cout << a << endl; Not allowed (private)
        cout << b << endl;    // Allowed (protected)
        cout << c << endl;    // Allowed (public)
    }
};

int main() {
    Derived d;        // Create object normally
    d.access();       // Call member function
    return 0;
}

3. What is the difference between virtual functions and pure virtual functions?

Virtual Function

Pure Virtual Function

A virtual function has an implementation in the base class and can be overridden in derived classes.A Pure Virtual Function is a member function of a base class that is only declared in a base class and defined in a derived class to prevent it from becoming an abstract class.
A virtual Function has its definition in its respective base class.              There is no definition in Pure Virtual Function and is initialized with a pure specifier (= 0).
The base class has a virtual function that can be represented or instanced; In simple words, its object can be made.A base class having pure virtual function becomes abstract that cannot be represented or instanced; In simple words, it means its object cannot be made.

Example:

C++
#include <iostream>
using namespace std;

// Base with virtual and pure virtual
class Base {
public:
    virtual void greet() {  // Virtual function
        cout << "Hello from Base" << endl;
    }

    virtual void pureGreet() = 0;  // Pure virtual function
};

// Derived implements pure virtual
class Derived : public Base {
public:
    void greet() override {
        cout << "Hello from Derived (Override)" << endl;
    }

    void pureGreet() override {
        cout << "Hello from Derived (Pure Virtual Implemented)" << endl;
    }
};

int main() {

    Derived d;
    Base* ptr = &d;

    ptr->greet();      // Calls overridden version
    ptr->pureGreet();  // Calls derived's implementation

    return 0;
}

4. Can a virtual function be called from a constructor? What happens when we do it?

Yes, a virtual function can be called from a constructor in C++, but the behavior is not what most people expect:

  • When a constructor is running, the derived part of the object is not yet constructed.
  • So, if you call a virtual function inside a constructor, the call will resolve to the base class version, not the derived one.
  • This happens because during base class construction, the object is treated as a base-class object only.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    Base() { 
        cout << "Base constructor\n";
        show();   // virtual call inside constructor
    }
    virtual void show() { cout << "Base show()\n"; }
};

class Derived : public Base {
public:
    Derived() { cout << "Derived constructor\n"; }
    void show() override { cout << "Derived show()\n"; }
};

int main() {
    Derived d;
    return 0;
}

Output
Base constructor
Base show()
Derived constructor

Notice that even though Derived overrides show(), the base version runs inside the base constructor.

5. What is Function Overriding?

  • Function overriding occurs when a derived class defines a function with the same name, parameters, and return type as in the base class.
  • It allows the derived class to provide its own implementation of the base function.
  • It is an example of runtime polymorphism (late binding), where the function executed is decided at runtime based on the object type.

Example:

C++
#include <iostream>
using namespace std;

class Animal {
public:
    // Virtual function allows overriding
    virtual void sound() {
        cout << "Animal makes a sound" << endl;
    }
};

class Dog : public Animal {
public:
    // Overrides the base class function
    void sound() override {
        cout << "Dog barks" << endl;
    }
};

int main() {
    Animal* a;       // Base class pointer
    Dog d;           // Derived class object
    a = &d;          // Base pointer points to derived object

    a->sound();      // Runtime polymorphism: Dog's version called
    return 0;
}

6. Explain the constructor & destructor in C++ .

  • A constructor is a special member function in C++ that has the same name as the class and is automatically called when an object is created. It is used to initialize the object’s data members.
  • A destructor is a special member function with the same name as the class, preceded by a tilde (~). It is automatically called when an object goes out of scope or is deleted, and is used to release resources or perform cleanup.
  • Constructors can be overloaded (multiple constructors with different parameters), but a class can only have one destructor, which cannot be overloaded.
  • Both constructors and destructors do not have a return type, not even void.
C++
#include <iostream>
using namespace std;

class Demo {
    int value;
public:
    // Constructor
    Demo(int v) {
        value = v;
        cout << "Constructor called, value = " << value << endl;
    }

    // Destructor
    ~Demo() {
        cout << "Destructor called for value = " << value << endl;
    }
};

int main() {
    Demo obj1(10);   // Constructor automatically called
    Demo obj2(20);   // Constructor automatically called
}   // Destructors automatically called here as objects go out of scope

Output
Constructor called, value = 10
Constructor called, value = 20
Destructor called for value = 20
Destructor called for value = 10

7. What happens if we define a virtual destructor but forget to mark the base class destructor as virtual?

If a base class destructor is not virtual, deleting a derived object via a base class pointer causes undefined behavior: only the base destructor runs, and the derived destructor is skipped. This leads to resource leaks.

To ensure proper cleanup, always make base class destructors virtual when using inheritance.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    ~Base() { cout << "Base Destructor\n"; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived Destructor\n"; }
};

int main() {
    Base* ptr = new Derived();
    delete ptr;
}

It's a silent issue no compile error, no crash, just leaked resources

8. Can constructors be private in C++? If yes, how are they used?

  • Yes, constructors can be private in C++.
  • When a constructor is private, objects of the class cannot be created directly outside the class.
  • Such constructors are usually used in:
    • Singleton design pattern: to restrict object creation and ensure only one instance exists.
    • Factory methods: object creation is controlled by static functions within the class.
    • Utility classes: where you don’t want anyone to instantiate the class (only static members are used).

Example (Singleton Pattern):

C++
#include <iostream>
using namespace std;

class Singleton {
private:
    static Singleton* instance;  // holds single instance
    Singleton() { cout << "Private constructor called\n"; }  // private constructor

public:
    static Singleton* getInstance() {
        if (instance == nullptr)
            instance = new Singleton();
        return instance;
    }

    void show() { cout << "Singleton instance working\n"; }
};

Singleton* Singleton::instance = nullptr;

int main() {
    // Singleton obj;   // Error: constructor is private
    Singleton* s = Singleton::getInstance();  // created via static method
    s->show();
}

Output
Private constructor called
Singleton instance working

Private constructors control instantiation, commonly used in design patterns.

9. When should we use multiple inheritance?

  • Use multiple inheritance when a class logically needs to derive features or behavior from more than one base class.
  • It is useful when a class needs to combine independent functionalities (e.g., a class that is both Printable and Serializable).
  • It can model real-world scenarios where an object belongs to multiple categories (e.g., Teacher who is also a Researcher).
  • However, it should be used carefully because it can lead to issues like the diamond problem, so prefer it only when there’s a clear and justifiable relationship.
multiple inheritances
Multiple Inheritances

Example:

C++
#include <iostream>
using namespace std;

// Parent class A
class A {
public:
    void showA() {
        cout << "Function from class A" << endl;
    }
};

// Parent class B
class B {
public:
    void showB() {
        cout << "Function from class B" << endl;
    }
};

// Child class C inherits from both A and B
class C : public A, public B {
public:
    void showC() {
        cout << "Function from class C" << endl;
    }
};

int main() {
    C obj;       // Object of derived class
    obj.showA(); // Access from class A
    obj.showB(); // Access from class B
    obj.showC(); // Own function
    return 0;
}

Output
Function from class A
Function from class B
Function from class C

This shows how a derived class C can reuse functionality from two parent classes A and B.

10. What is virtual inheritance?

  • Virtual inheritance is a C++ mechanism used to solve the diamond problem in multiple inheritance.
  • It ensures that when a class is derived from two classes that have a common base, only one copy of the common base is inherited, avoiding ambiguity and duplication.
  • Without virtual inheritance, each path in the inheritance hierarchy brings its own copy of the base class, leading to multiple instances and conflicts.

Without Virtual Inheritance – Diamond Problem:

C++
#include <iostream>
using namespace std;

class Base {
public:
    void show() { cout << "Base class" << endl; }
};

class A : public Base {};
class B : public Base {};
class C : public A, public B {};  // Diamond problem

int main() {
    C obj;
    // obj.show();  // Ambiguous: which Base::show() ?
}

With Virtual Inheritance- Solves Ambiguity:

C++
#include <iostream>
using namespace std;

class Base {
public:
    void show() { cout << "Base class" << endl; }
};

class A : virtual public Base {};
class B : virtual public Base {};
class C : public A, public B {};  // Only one copy of Base

int main() {
    C obj;
    obj.show();  // No ambiguity
}

11. Can a derived class access private members of the base class? How?

A derived class cannot directly access private members of a base class. Access is possible only through:

  1. protected members (directly accessible in derived).
  2. public or protected getters/setters in base.
  3. Declaring the derived class (or function) as a friend.

Example:

C++
#include <iostream>
using namespace std;

class Base {
private:
    int x = 42;
    friend class Derived;  // Grant access
};

class Derived : public Base {
public:
    void show() {
        cout << "Accessing private x: " << x << endl;
    }
};

int main() {
    Derived d;
    d.show();
}

12. What are the different types of polymorphism in C++?

There are two types of polymorphism

1. Compile Time Polymorphism or Static Binding: This type of polymorphism is achieved during the compile time of the program which results in it making a bit faster than Run time. Also, Inheritance is not involved in it. It is comprised of 2 further techniques:

  • Function Overloading: When there are multiple functions with the same name but different parameters then this is known as function overloading.
C++
// same name different arguments
int GFG() {}
int GFG(int a) {}
float GFG(double a) {}
int GFG(int a, double b) {}
  • Operator Overloading: It is basically giving practice of giving a special meaning to the existing meaning of an operator or in simple terms redefining the pre-redefined meaning
C++
class GFG {
    // private and other modes
    statements public returnType
    operator symbol(arguments){ statements } statements
};

2. Run-Time Polymorphism or Late Binding: Run-time polymorphism takes place when functions are invoked during run time. 

  • Function Overriding: Function overriding occurs when a base class member function is redefined in a derived class with the same arguments and return type.
C++
// C++ program to demonstrate
// Function overriding
#include<iostream> 
using namespace std;
class GFG {
public:
    virtual void display()
    {
        cout << "Function of base class" << endl;
    }
};
class derived_GFG : public GFG {
public:
    void display()
    {
        cout << "Function of derived class" << endl;
    }
};
int main()
{
    derived_GFG dg;
    dg.display();
    return 0;
}

Output:

Function of derived class

13. What happens when we override a function but forget to use virtual in the base class?

  • If you override a function in the derived class but the base class function is not marked virtual, then function overriding won’t work as runtime polymorphism.
  • Instead, function hiding occurs when the base class function is hidden by the derived class function if called through a derived object.
  • But if you use a base class pointer or reference, the base version is always called (compile-time binding), not the derived one.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    void show() { cout << "Base\n"; }
};

class Derived : public Base {
public:
    void show() { cout << "Derived\n"; }
};

int main() {
    Base* ptr = new Derived();
    ptr->show();  // Base version called
}

Output
Base

There is no runtime failure, just static binding to the base version.

14. What is object slicing in C++? How does it occur?

  • Object slicing happens in C++ when a derived class object is assigned to a base class object by value.
  • In this process, only the base part of the derived object is copied, and the derived-specific members (extra data or overridden behavior) are “sliced off”.

This usually occurs when:

  • Passing a derived object by value to a function that takes a base class parameter.
  • Assigning a derived object to a base class variable (not pointer or reference).
  • To avoid slicing, use pointers or references to base instead of objects by value.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    int x = 5;
    void print() { cout << "Base x = " << x << endl; }
};

class Derived : public Base {
public:
    int y = 10;
    void print() { cout << "Derived y = " << y << endl; }
};

int main() {
    Derived d;
    Base b = d;  // Object slicing
    b.print();   // Only base part copied
    // b.y;  // Error: y is sliced off
}

15. What is a virtual destructor?

  • A virtual destructor in C++ makes sure that when a base class pointer deletes a derived class object, the derived destructor is called first, followed by the base destructor.
  • Without it, only the base destructor executes, which can lead to incomplete cleanup and resource leaks.
  • It is mainly used in polymorphic base classes where objects may be deleted through a base pointer.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    Base() { cout << "Base constructor\n"; }
    virtual ~Base() { cout << "Base destructor\n"; }  // Must be virtual
};

class Derived : public Base {
public:
    Derived() { cout << "Derived constructor\n"; }
    ~Derived() { cout << "Derived destructor\n"; }
};

int main() {
    Base* ptr = new Derived();  // Base pointer to derived
    delete ptr;  // Correct destructor chain due to virtual destructor
}

16. Is destructor overloading possible? If yes then explain and if no then why?

  • Destructor overloading is not possible in C++. A class can have only one destructor, and it cannot take parameters or have a return type.
  • The reason is: the destructor is called automatically by the compiler when an object goes out of scope or is deleted, so it must have a fixed, predictable signature.
  • If overloading were allowed, the compiler wouldn’t know which destructor to call during cleanup, leading to ambiguity.

Example:

C++
class MyClass {
public:
    ~MyClass() {}       
};

17. What do you know about friend class and friend function?

  • A friend function is a non-member function that has access to the private and protected members of a class. It is declared using the keyword friend inside the class.
  • A friend class is a class that can access the private and protected members of another class. The friendship is declared inside the class using friend class.
  • Friendship is not mutual (if A is a friend of B, B isn’t automatically a friend of A) and not inherited (derived classes don’t inherit friendship).
  • They are mainly used when two classes or functions need close cooperation and direct access to each other’s internals.

Example:

C++
#include <iostream>
using namespace std;

class A {
private:
    int secret = 42;

public:
    // Friend function
    friend void revealSecret(A obj);

    // Friend class
    friend class B;
};

// Friend function can access private data
void revealSecret(A obj) {
    cout << "Friend function accessed secret: " << obj.secret << endl;
}

// Friend class can access private data
class B {
public:
    void showSecret(A obj) {
        cout << "Friend class accessed secret: " << obj.secret << endl;
    }
};

int main() {
    A a;
    B b;

    revealSecret(a);  // Using friend function
    b.showSecret(a);  // Using friend class
    return 0;
}

Output
Friend function accessed secret: 42
Friend class accessed secret: 42

This shows that both a friend function and a friend class can directly access private members of another class.

18. What is an abstract class and when do you use it?

  • A class with at least one pure virtual function (virtual void func() = 0;).
  • Cannot be instantiated directly.
  • Provides a common interface for derived classes.
  • Enforces implementation of specific functions in subclasses.
  • Enables runtime polymorphism.

When to use an abstract class?

  • When you want to define a base class that outlines a common interface.
  • To ensure derived classes implement certain functions.
  • When you need to share some common functionality among related classes.
  • To enable polymorphic behavior through base class pointers or references.

Example:

C++
#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() = 0; // Pure virtual → makes Shape abstract
};

class Circle : public Shape {
public:
    void draw() override {
        cout << "Drawing Circle\n";
    }
};

int main() {
    Shape* ptr = new Circle();
    ptr->draw();    // Polymorphic behavior
    delete ptr;
}

Output
Drawing Circle

19. What are the static data members and static member functions?

A static data member belongs to the class, not to individual objects. Only one copy exists, shared by all objects.

Syntax:

static Data_Type Data_Member; 

A static member function can access only static members of the class and can be called using the class name.

Syntax:

classname::function name(parameter);

Example:

C++
#include <iostream>
using namespace std;

class Counter {
    static int count;  // Static data member
public:
    Counter() { ++count; }
    static void showCount() {  // Static function
        cout << "Count = " << count << endl;
    }
};

int Counter::count = 0;  // Initialize static member

int main() {
    Counter a, b, c;
    Counter::showCount();  // Call static function via class
}

20. Can we call a virtual function from a constructor?

Yes, we can call a virtual function from a constructor, but during base class construction the derived part of the object is not yet initialized. Hence, the base class version of the function is called, not the derived version.

Example:

C++
#include <iostream>
using namespace std;

class Base {
public:
    Base() {
        cout << "Base Constructor\n";
        virtualFunc();  // Calls Base version only
    }

    virtual void virtualFunc() {
        cout << "Base::virtualFunc()\n";
    }

    virtual ~Base() {}
};

class Derived : public Base {
public:
    void virtualFunc() override {
        cout << "Derived::virtualFunc()\n";
    }
};

int main() {
    Derived d;
    return 0;
}

During Base constructor execution, Derived is not yet constructed, so virtualFunc() is not overridden yet.


Article Tags :

Explore