Search code examples
c++ooppolymorphismc++14pure-virtual

Virtual function input Argument type


I am trying to understand inheritance and polymorphism. When I run this :

    #include<iostream> 
    using namespace std; 

class Base 
{ 
int x; 
public: 
    virtual Base* fun() = 0; 
    int getX() { return x; } 
}; 

// This class inherits from Base and implements fun() 
class Derived: public Base 
{ 
    
public: 
    int y;
    Derived* fun() { 
        Derived *d = new Derived;
        d->y = 2;
        return d;
        
    } 
}; 

int main(void) 
{ 
    Derived d;
    Derived *p = d.fun();
  cout<< p->y;
} 

This works fine as it is legal for a derived class to override a virtual function using a different return type as long as the return type is covariant with the original return type

But what if the virtual function contain the input argument of type Base*. Like :

#include<iostream> 
using namespace std; 

class Base 
{ 
int x; 
public: 
    virtual Base* fun(Base * t) = 0; 
    int getX() { return x; } 
}; 

// This class inherits from Base and implements fun() 
class Derived: public Base 
{ 
    
public: 
    int y;
    Derived* fun(Derived *t) { 
        Derived *d = new Derived;
        d->y = t->y;
        return d;
        
    } 
}; 

int main(void) 
{ 
    Derived d;
    Derived *p = d.fun();
  cout<< p->y;
} 

This is throwing error error: invalid new-expression of abstract class type ‘Derived’ Derived *d = new Derived; which I understand it means that compiler is not recognising the implementation of the virtual function and considering the class ``Derived``` as abstract.

So how can we override virtual function of this type ?? I tried to search it , but didn't find any reference. If similar question exists , let me know. Thanks


Solution

  • If I needed this in my own code. I'd write the new derived class like this:

    // This class inherits from Base and implements fun() 
    class Derived: public Base 
    { 
        
    public: 
        int y;
        Derived* fun(Base *t) { 
            Derived *d = new Derived;
            Derived* input = dynamic_cast<Derived *>(t);
            ASSERT(input);    // Cause the debug version to throw an exception so the error can be debugged
            if(input)
               d->y = t->y;
            else
               d->y = 0;    // Or the default of your choice. 
            return d;
            
        } 
    }; 
    

    This introduces a potential runtime error if the base type passed in is not the correct derived type. But I don't see a way to avoid it.

    The other options I see are use templates. Where the derived type requires the derived type to be passed in. Or simply create a new function that takes the derived type as input and also overrides fun(Base *t);