OOP Concepts in C++ for GATE CS
Classes, inheritance, polymorphism, virtual functions, abstract classes — all OOP in C++ tested in GATE with output-prediction examples.
Last updated: April 2026 | GATE CS 2024–2026 syllabus
Key Takeaways for GATE
- Encapsulation: data + methods in one class.
privatemembers inaccessible outside. - Constructor order: Base → Derived. Destructor order: Derived → Base (reverse).
- Virtual function: runtime dispatch via vtable.
virtualkeyword in base. Overriding in derived. - Pure virtual (
= 0): makes class abstract. Cannot instantiate abstract class. - Polymorphism via base pointer:
Base *p = new Derived; p->vfunc();calls Derived’s version. - Destructor must be virtual in base class to avoid memory leaks when deleting via base pointer.
- Diamond problem: Use
virtualbase class to share single copy in multiple inheritance.
1. Four Pillars of OOP
| Pillar | Definition | C++ Mechanism |
|---|---|---|
| Encapsulation | Bundle data + methods; restrict direct access | private/protected/public |
| Abstraction | Expose essential interface, hide implementation | Abstract classes, interfaces |
| Inheritance | Derive new class from existing, reuse code | class D : public B |
| Polymorphism | Same interface, different behaviour | Virtual functions, overloading |
2. Classes & Objects
class Circle {
private:
double radius; // data member (hidden)
public:
Circle(double r) : radius(r) {} // constructor
double area() { return 3.14159 * radius * radius; } // method
~Circle() {} // destructor
};
Circle c(5.0); // object on stack
Circle *p = new Circle(3.0); // object on heap
delete p;struct vs class in C++: Only difference — default access. struct: public. class: private.
3. Constructors & Destructors
Default: no parameters. Copy: takes const reference to same class. Parameterised: takes other args.
Initialiser list (preferred):
class A {
int x, y;
public:
A(int a, int b) : x(a), y(b) {} // members initialised before constructor body
};Constructor/Destructor order — critical for GATE:
class A { public: A(){cout<<"A";} ~A(){cout<<"~A";} };
class B : public A { public: B(){cout<<"B";} ~B(){cout<<"~B";} };
B b; // Output: A B (on creation)
// ~B ~A (on destruction)Rule: Constructor — Base first, then Derived. Destructor — Derived first, then Base.
4. Inheritance
class Derived : public Base { ... };Types of inheritance:
| Inheritance type | Base public | Base protected | Base private |
|---|---|---|---|
| public | public | protected | inaccessible |
| protected | protected | protected | inaccessible |
| private | private | private | inaccessible |
Private members of base are never directly accessible in derived (even with public inheritance).
Default inheritance for class: private. For struct: public.
5. Virtual Functions & Polymorphism
class A { public: void f() { cout << "A"; } };
class B : public A { public: void f() { cout << "B"; } };
A *p = new B;
p->f(); // prints "A" — pointer type is A*, so A::f() calledWith virtual (dynamic dispatch):
class A { public: virtual void f() { cout << "A"; } };
class B : public A { public: void f() { cout << "B"; } };
A *p = new B;
p->f(); // prints "B" — object is B, so B::f() called via vtablevtable: Each class with virtual functions has a vtable (array of function pointers). Each object has a vptr pointing to its class’s vtable. Runtime lookup: vptr → vtable → correct function.
Virtual destructor: Essential when deleting derived object via base pointer.
A *p = new B; delete p; // Without virtual ~A(): UB. With virtual ~A(): ~B() then ~A() called.
6. Abstract Classes
virtual void f() = 0; — no implementation in class.Abstract class: any class with ≥1 pure virtual function.
Cannot instantiate:
Shape s; — compile error if Shape is abstract.Must override: Derived class must implement ALL pure virtual functions to be concrete.
class Shape { // abstract
public:
virtual double area() = 0; // pure virtual
virtual ~Shape() {} // virtual destructor
};
class Circle : public Shape { // concrete
double r;
public:
Circle(double r) : r(r) {}
double area() override { return 3.14*r*r; } // override keyword (C++11)
};7. Access Specifiers Summary
| Specifier | Same class | Derived class | Outside class |
|---|---|---|---|
| public | Yes | Yes | Yes |
| protected | Yes | Yes | No |
| private | Yes | No | No |
8. Multiple Inheritance & Diamond Problem
A
/ \
B C
\ /
D
// D gets TWO copies of A's members — ambiguityFix — virtual base class:
class A { public: int x; };
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
// Only ONE copy of A in DVirtual inheritance adds overhead (vptr for virtual base). Constructor of A called by D directly.
9. GATE Examples
class A {
public:
A() { cout << "A "; }
~A() { cout << "~A "; }
};
class B : public A {
public:
B() { cout << "B "; }
~B() { cout << "~B "; }
};
int main() { B b; } Constructor: A first (base), then B (derived). Destructor (on scope exit): ~B first, then ~A.
Output: A B ~B ~A
class A {
public:
virtual void f() { cout << "A"; }
};
class B : public A {
public:
void f() { cout << "B"; }
};
A *p = new B;
p->f();Virtual dispatch: object is B, so B::f() is called. Output: B
class X {
public:
virtual void g() = 0;
void h() { cout << "h"; }
};
X obj; // ?X has a pure virtual function g() — X is abstract. X obj; is a compile error.
10. Common Mistakes
- Non-virtual destructor in polymorphic base:
A *p = new B; delete p;with non-virtual destructor calls only A’s destructor — B’s destructor skipped, causing memory/resource leaks. - Forgetting
overridekeyword: Withoutoverride, a function in the derived class with wrong signature silently creates a new function instead of overriding — the virtual dispatch doesn’t reach it. - Accessing private base members in derived: Private members are never accessible in derived class even with public inheritance. Use protected for members that derived classes need to access.
- Constructor order confusion: Base constructor is always called before derived, regardless of order in derived’s initializer list. Destructor order is always reversed.
- Calling virtual functions from constructor/destructor: Virtual dispatch does NOT work in constructors/destructors — the call goes to the class being currently constructed, not the most-derived class.
11. FAQ
- What is the difference between virtual and non-virtual functions in C++?
- Non-virtual functions use static dispatch — the function called is determined at compile time based on the pointer/reference type. Virtual functions use dynamic dispatch via vtable — the function called is determined at runtime based on the actual object type. This is what makes runtime polymorphism possible: a Base* pointing to a Derived object will call Derived’s virtual function, not Base’s.
- What is the order of constructor and destructor calls in inheritance?
- Constructors execute base-first: if D inherits from C inherits from B inherits from A, the order is A→B→C→D. Destructors execute in reverse: D→C→B→A. This guarantees the base class is fully constructed before derived adds to it, and derived is fully destroyed before base tears down.
- What is a pure virtual function and abstract class?
- A pure virtual function is declared with = 0 in the base class and has no implementation there. Any class containing at least one pure virtual function is abstract — it cannot be instantiated. Derived classes must provide implementations for all pure virtual functions (otherwise they too are abstract). Abstract classes act as interfaces in C++.
- What is the diamond problem in multiple inheritance?
- When class D inherits from B and C, and both B and C inherit from A, D gets two separate copies of A’s members (one through B, one through C). Accessing A’s members from D is ambiguous. The fix is virtual inheritance: class B : virtual public A and class C : virtual public A — this ensures only one shared copy of A exists in D.