Search code examples
c++ooppolymorphismruntimecompile-time

Method overriding in c++ : is it compile time or run time polymorphism?


In C++, Is function overriding run time polymorphism or compile time polymorphism? I think it is compile time polymorphism because every information which is required to call the appropriate function is known to compiler early. As in the code below, obj.disp(); Here compiler knows obj is the object of base class so it will immediately resolve the call to disp() function of base class. and same for obj2.disp(); Here compiler knows obj2 is the object of derived class so it will call disp() function of derived class. I don't see why it is called run-time polymorphism.

Still in JAVA, people call function overriding as run time polymorphism. Please explain somebody....

#include <iostream>
using namespace std;

class A {
public:
  void disp(){
     cout<<"Super Class Function"<<endl;
  }
};

class B: public A{
public:
  void disp(){
     cout<<"Sub Class Function";
  }
};

int main() {
  //Parent class object
  A obj;
  obj.disp();
  //Child class object
  B obj2;
  obj2.disp();
  return 0;
}

Solution

  • Is function overriding run time polymorphism or compile time polymorphism

    You can only override virtual methods and those are there to support run-time polymorphism. A clever compiler can probably manage without vtables (for virtual dispatch) if all facts are known during compile time, but if they aren't, it has to be resolved in run-time.

    Let a random number generator create objects from different child classes and pass them to a function accepting a base class pointer (or reference) and that function would still be able to call the object's overridden functions. This is resolved in run-time. Functions hiding base class functions or child class' overloads would not be available.

    An example (without randomization):

    #include <iostream>
    
    class Foo {
    public:
        void not_virtual() { std::cout << "not_virtual\n"; }
        virtual void func() = 0;
    
        virtual ~Foo() = 0;
    };
    
    Foo::~Foo() {}
    
    void Foo::func() {
        std::cout << "default implementation\n";
    }
    
    class FooImpl : public Foo {
    public:
        void not_virtual() {      // hiding - Foo's not_virtual()
            std::cout << "not_virtual, but in FooImpl\n";
        }
        void not_virtual(int x) { // overloading - same name, different signature
            std::cout << "not_virtual " << x << "\n";
        }
        void func() override { std::cout << "Impl\n"; }
    };
    
    void interface_user(Foo& x) { // slice away all but the Foo part of the object
                                  // but
        x.func();                 // func() is in the vtable, call child class' function
        x.not_virtual();          // not in the vtable, call Foo's function
        // x.not_virtual(2);      // error: Foo doesn't have this overload
    }
    
    int main() {
        FooImpl f;
    
        f.func();          // calling overridden func
        f.not_virtual();   // calling function hiding the base class function
        f.not_virtual(1);  // calling overloaded func
    
        interface_user(f); // slicing - the function takes a Foo&
    }
    

    Output:

    Impl
    not_virtual, but in FooImpl
    not_virtual 1
    Impl
    not_virtual