Search code examples
c++11pointerspolymorphismoverloading

C++11 Polymorphism : Call derived class method from base class pointer


In summary, I believe that the answer to my question is no. However, I will have hope and defer to those smarter than I.

I would like to call a class method of a derived class from the pointer to the base class. The inherited method(s) that are overloaded and desired to be called are pure virtual. I am able to get it to work in certain cases but not in one particular case, where the pure virtual method contains ellipsis placeholder for arguments.

The essence of what I desire is pasted below, any fixes and/or suggestions are greatly appreciated, thank you.

    #include <iostream>

    class A
    {
        public:
            virtual void setup()=0;
            virtual void callFunction(std::string str, ...)=0;
    };

    class B: public A
    {
        public:
            virtual void setup() {};        
            virtual void callFunction(std::string str, ...) { std::cout<<"\nB::callFunction("<<str<<")\n"; }; //compiles: not desired: a->callFunction("Hello World", 987); executes as B::callFunction
            //virtual void callFunction(std::string str, ...)=0; compile error: error: cannot declare variable 'c' to be of abstract type 'C'
    };

    class C: public B
    {
        public:
            void setup() { std::cout<<"\nC::setup\n"; };
            void callFunction(std::string str, int i) { std::cout<<"\nC::callFunction("<<str<<") = "<<i<<"\n"; };
    };

    int main()
    {          
        C c;
        A* a = (A*) new C;
        
        c.setup();
        c.callFunction("Hello World", 123);
        
        a->setup(); //WHY: does this pure virtual function still execute C::setup, this is desired for pure virtual method callFunction derived from class A
        a->callFunction("Hello World", 987);
        
        return 0;
        
    }

Solution

  • As a conclusion from the comments:

    You cannot influence virtual dispatch by overloading the virtual function in a derived class.

    Overload resolution and virtual dispatch are orthogonal and the former happens before the latter.

    So what you can do is declare multiple overloads, which are individually virtually dispatched.

    In your case in the question this simply requires adding the int overload as a pure virtual to A:

    class A
    {
        public:
            virtual void setup()=0;
            virtual void callFunction(std::string, ...)=0;
            virtual void callFunction(std::string, int)=0;
    };
    

    To make sure that virtual function implementations are matched properly to these overloads, you should add the override specifier to all the implementations in the derived classes, e.g.:

    void callFunction(std::string str, int i) override { std::cout<<"\nC::callFunction("<<str<<") = "<<i<<"\n"; };
    

    If you need to support more argument types, simply add another pure virtual overload to A and implement it somewhere in the inheritance hierarchy.