Fundamentals Interview Bank

Learning Objectives

Answer the most common OOP fundamentals questions precisely and with examples.

Avoid the classic half-correct answers interviewers probe.

Prerequisites: Stage 1, Modules 10–13.

Intuition and Definition

A strong fundamentals answer has three parts: a precise definition, a concrete example (ideally code-level), and a trade-off or pitfall. Interviewers use fundamentals to check whether you understand mechanisms, not just vocabulary.

Why It Matters

Fundamentals questions open almost every OOP interview; weak answers here end interviews early.

Syntax and Language Notes

Answer in the interviewer's language when possible and mention language differences when relevant (C++ value semantics vs Java references, C# non-virtual by default, Python duck typing).

Complete Example

One program that demonstrates five fundamentals at once — overloading vs overriding, the virtual destructor, slicing, shallow vs deep copy, and identity vs equality:

#include <iostream>
#include <memory>
#include <string>
#include <vector>

struct Base {
    virtual ~Base() { std::cout << "  ~Base\n"; }
    virtual std::string who() const { return "Base"; }
    static std::string greet(int) { return "greet(int)"; }           // overload set
    static std::string greet(const std::string&) { return "greet(string)"; }
};
struct Derived : Base {
    ~Derived() override { std::cout << "  ~Derived\n"; }
    std::string who() const override { return "Derived"; }            // override
};

struct Shallow { int* p; };                                           // copies share the int
struct Deep { std::vector<int> v; };                                  // copies own their data

int main() {
    std::cout << "1 overload: " << Base::greet(1) << ", " << Base::greet("x") << "\n";
    std::unique_ptr<Base> b = std::make_unique<Derived>();
    std::cout << "2 override via base pointer: " << b->who() << "\n";
    Derived d;
    Base sliced = d;                                                  // copy of the Base part only
    std::cout << "3 slicing: " << sliced.who() << "\n";

    int x = 1;
    Shallow s1{&x}; Shallow s2 = s1; *s2.p = 99;
    Deep d1{{1}}; D
…
1 overload: greet(int), greet(string)
2 override via base pointer: Derived
3 slicing: Base
4 shallow copy sees change: 99, deep copy unaffected: 1
5 equal: 1, same object: 0
destroying the Derived owned through Base*:
  ~Derived
  ~Base
end of main:
  ~Base
  ~Derived
  ~Base

Step-by-Step Walkthrough

Overloads are chosen at compile time by argument type.

The override is chosen at run time through the base pointer.

Copying a Derived into a Base value slices it.

Copying a struct with a raw pointer copies the pointer (shared int); copying a vector copies its elements.

Equal values, distinct objects. Then the virtual destructor runs both destructors when deleting through Base*; at the end of main, sliced (a Base) and d (a Derived) are destroyed.

Common Mistakes

Defining encapsulation as "private fields with getters and setters".

Saying "polymorphism means overloading" (or only overriding).

Confusing aggregation and composition, or abstraction and encapsulation.

Not knowing what happens without a virtual destructor.

Rote definitions without examples.

Trade-offs and Alternatives

When a question has a "depends" answer (inheritance vs composition, interface vs abstract class), say what it depends on and give the decision rule.

Real-World Use

These questions map directly to code-review topics: slicing bugs, missing virtual destructors, shallow copies of owning pointers, identity/equality mix-ups.

Practice

Q1. What is OOP?

Answer: A paradigm that organises software around objects combining state and behaviour, using abstraction, encapsulation, inheritance and polymorphism to manage complexity and change (Module 1).

Q2. Class vs object?

Answer: A class is a type definition; an object is a run-time instance with its own state and identity (Module 2).

Q3. Abstraction vs encapsulation?

Answer: Abstraction decides *what* to expose (the essential operations); encapsulation *protects* the state behind them so invariants hold (Modules 3–4).

Q4. Inheritance vs composition?

Answer: Inheritance models substitutable is-a relationships and couples you to the base's implementation; composition holds other objects and delegates, giving looser coupling and run-time flexibility. Prefer composition unless substitutability is genuine (Module 7).

Q5. Overloading vs overriding?

Answer: Overloading: same name, different parameters, chosen at compile time. Overriding: derived class replaces a virtual function with the same signature, chosen at run time (Modules 8, 15).

Q6. Compile-time vs run-time polymorphism?

Answer: Compile time: overloads and templates/generics. Run time: virtual dispatch through base references/pointers or interfaces (Module 8).

Q7. Interface vs abstract class?

Answer: An interface is a pure contract (in Java/C# possibly with default methods, no instance state); an abstract class can hold state and partial implementation but limits you to single inheritance in Java/C#. Use interfaces for capabilities, abstract classes for shared implementation in a closed family (Module 4).

Q8. Static vs instance members?

Answer: Instance members belong to each object; static members to the class, shared by all objects and usable without an instance (Module 10).

Q9. Constructor vs method?

Answer: A constructor initialises a new object and establishes its invariants; it has no return type and runs once per object. Methods operate on existing objects (Module 5).

Q10. What are this and super/base?

Answer: this refers to the current object; super (Java/TS/Python super()), base (C#) or Base:: (C++) access the parent implementation (Module 11).

Q11. What do access specifiers do?

Answer: Control which code may access members (public/protected/private, plus package/internal variants) — the mechanism behind encapsulation (Module 3).

Q12. Association vs aggregation vs composition?

Answer: Association: objects know each other. Aggregation: whole–part with independent lifetimes. Composition: the whole owns the part; the part dies with it (Module 9).

Q13. Shallow vs deep copy?

Answer: Shallow copies references/pointers (shared sub-objects); deep copies duplicate what is owned (Module 12).

Q14. Identity vs equality?

Answer: Identity: the same object. Equality: equivalent state according to the type's definition (Modules 2, 12).

Q15. Why does a C++ polymorphic base need a virtual destructor?

Answer: Deleting a derived object through a base pointer is undefined behaviour unless the base destructor is virtual; with it, the derived destructor runs first (Module 4).

Q16. What is object slicing?

Answer: Copying a derived object into a base object by value, losing the derived part and its dynamic behaviour (Module 8).

Q17. What is the diamond problem?

Answer: Multiple inheritance paths to one base creating duplicate subobjects and ambiguity; C++ uses virtual inheritance, Java/C# use interfaces, Python uses the MRO (Module 7).

Q18. What is method hiding?

Answer: A derived member with the same name hides base members instead of overriding them (C++ name hiding; C# new); which one runs depends on the static type (Modules 7, 79).

Q19. What is an immutable object and why use one?

Answer: An object whose state can't change after construction; safe to share across threads and callers, no defensive copies, easy reasoning (Modules 10, 59).

Interview Question

Q1. "Explain polymorphism to a junior developer in two minutes, with code."

Answer: "Polymorphism lets one piece of code work with many types. In C++, void render(const Shape& s) { s.draw(); } calls Circle::draw or Square::draw depending on the actual object, because draw is virtual — that's run-time polymorphism. Overloaded functions and templates are compile-time polymorphism: the compiler picks the version. The benefit is that adding a new shape doesn't change render; the cost is an indirect call and the need to pass objects by reference or pointer to avoid slicing."

Quick Quiz

Q1. Which is chosen at run time: overload or override?

Answer: Override.

Q2. Composition implies which lifetime relationship?

Answer: The part's lifetime is bounded by the whole's.

Q3. What prevents slicing?

Answer: Passing and storing polymorphic objects by reference or (smart) pointer.

Summary

Define precisely, show an example, mention a trade-off or pitfall.

Related: Stage 1, Modules 10–13.