Search code examples
c++oopvirtualdispatch

Example of virtual function method call that does not exist at compile time?


The wikipedia article on virtual functions states the following:

Virtual functions allow a program to call methods that don't necessarily even exist at the moment the code is compiled.

Unfortunately it doesn't give an example, and states "citation needed."

It gives general code in C++ and C, but they don't explain how a function call could be generated after compile time. Can someone please provide an example, preferably in C++, or failing that, Java?


Solution

  • most typical use of virtual functions is when writing interfaces, basically you have an interface in some header file

    // some_header.h
    class ICar
    {
    public:
        virtual void Drive() {};
        virtual ~ICar() {}
    };
    

    a library gets compiled into a .dll or .lib or .so with a function that consumes this interface.

    // library1.dll or library1.so
    // static or dynamic linking make no difference in this
    void DriveCar(ICar& car)
    {
        car.Drive();
    }
    

    then you main program will create a conrete class that implements that interface and pass it to that library.

    #include <iostream>
    
    void DriveCar(ICar& car); // need to link library1
    
    class MiniVan: public ICar
    {
    public:
        // overrides ICar::Drive
        void Drive() override { std::cout << "vrooom!\n";}
    };
    
    int main()
    {
        MiniVan van;
        DriveCar(van);  // MiniVan is an ICar
    }
    

    when library1 was compiled it had no idea MiniVan existed, but through virtual functions we were able to modify library1 behavior after it was compiled.

    in reality the behavior of the library was not modified, it was calling a function pointer, and we supplied a different function for this library to call, you could easily replace the above code with function pointers as follows.

    using func_type = void(*)();
    
    void DriveCar(func_type func)
    {
        func();
    }
    
    void MiniVanDrive()
    {
    }
    
    int main()
    {
       DriveCar(MiniVanDrive);
    }
    

    while not equivalent, using interfaces and virtual functions is cleaner for the readers, but it is not magic.