OOPS Interview Questions · Question 07

What is the difference between compile-time polymorphism and runtime polymorphism?

Interview preparation resource from Gate Smashers.

Interview-ready answer

Compile-time polymorphism is resolved by the compiler using information available at the call site, such as argument types and number of arguments. Common examples are method/function overloading and operator overloading. Runtime polymorphism is resolved while the program runs: a call through a base-class or interface reference invokes the implementation for the object’s actual runtime type, typically through method overriding and dynamic dispatch.

Java — overloading and overridingjava
class PolymorphismDemo {
    static class Calculator {
        int add(int a, int b) {
            return a + b;
        }

        double add(double a, double b) {
            return a + b;
        }
    }

    static class Animal {
        void speak() {
            System.out.println("Animal speaks");
        }
    }

    static class Dog extends Animal {
        @Override
        void speak() {
            System.out.println("Dog barks");
        }
    }

    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        System.out.println(calculator.add(1, 2));
        System.out.println(calculator.add(1.0, 2.0));

        Animal animal = new Dog();
        animal.speak();
    }
}
C++ — overloading and virtual overridingcpp
#include <iostream>

void func(int x) {
    std::cout << "int: " << x << '
';
}

void func(double x) {
    std::cout << "double: " << x << '
';
}

struct Base {
    virtual void speak() {
        std::cout << "Base
";
    }

    virtual ~Base() = default;
};

struct Derived : Base {
    void speak() override {
        std::cout << "Derived
";
    }
};

int main() {
    func(10);
    func(3.14);

    Base* base = new Derived();
    base->speak();
    delete base;
}
Understand it clearly

Compile-time polymorphism

Compile-time polymorphism, also called static polymorphism, selects the target operation before the program executes. For example, when overloaded methods have different parameter lists, the compiler chooses the applicable overload from the argument types at the call site.

The selected overload is fixed in the generated program for that call. It does not require inheritance. Templates in C++ are another form of compile-time polymorphism; generic mechanisms in other languages can have different implementation and dispatch behavior.

  • Typical mechanisms: Function or method overloading, operator overloading, and C++ templates.
  • Selection basis: Compile-time information, such as declared argument types, argument count, and available overloads.

Runtime polymorphism

Runtime polymorphism, also called dynamic polymorphism, selects an overridden implementation according to the actual object at runtime. It allows code written against a common base class or interface to work with multiple concrete implementations.

For example, if an Animal reference refers to a Dog object, calling speak() invokes Dog.speak() when the method participates in dynamic dispatch. The language runtime may implement this with a dispatch table, but that is an implementation detail rather than a universal requirement.

  • Typical mechanisms: Method overriding through virtual methods, abstract methods, or interface methods, depending on the language.
  • Requirement: A common polymorphic type relationship, such as a base class or interface; the exact language mechanism varies.

Trade-offs

Compile-time polymorphism is useful when the operation can be selected from static type information. It often enables direct calls and compiler optimization, although optimization results depend on the compiler and build settings.

Runtime polymorphism is useful when behavior must vary with the concrete object type, such as when processing different implementations through one interface. Dynamic dispatch can add indirection, though modern compilers and runtimes may optimize some calls when the target is known.

  • Use compile-time polymorphism: When the desired operation is determined by the call’s declared types and signatures.
  • Use runtime polymorphism: When clients should depend on a common abstraction while concrete implementations can vary at runtime.
Quick comparison
BasisCompile-time polymorphismRuntime polymorphism
Binding timeResolved by the compiler before execution.Resolved during execution based on the object’s runtime type.
Common mechanismsOverloading, operator overloading, and C++ templates.Overriding with virtual, abstract, or interface methods.
Inheritance or interface relationshipNot required.Typically uses a common base type or interface.
Call selectionBased on compile-time information at the call site.Based on the concrete object referenced at runtime.
Performance characteristicsCan use direct calls and may be optimized or inlined.May use dynamic dispatch and an indirect call; implementations may optimize known targets.