overriden virtual function is not getting called

20,465

Solution 1

It looks like you have provided a simplified version of your code to make it more readable, but you have oversimplified inadvertently.

The most likely reasons for your behaviour are:

  • Slicing in FuncCaller() (see quamrana's answer for the details)
  • Wrong overriding, such as making the derived class function const, while the base class function is not const

EDIT: After reading the edited question, it is clearly the second reason. You are not overriding the base class function, but hiding it in the derived classes with a new definition. You need to keep exactly the same signature (covariance does not apply here, since the function returns void) in the derived classes. In code, you need to do either:

class SomeParam;
class IBase
{
public:
    virtual void Func(SomeParam* param = NULL)
    {
        cout << "Base func";
    }
};

class DerivedA : public IBase
{
public:
    void Func(SomeParam* param = NULL)
    {
        //do some custom stuff
        cout << "DerivedA func";
        IBase::Func();
    }
};

class DerivedB : public IBase
{
public:
    void Func(SomeParam* param = NULL)
    {
        //do some custom stuff
        cout << "DerivedB func";
        IBase::Func();
    }
};

//at somewhere else
void FuncCaller(IBase *instance1, IBase *instance2)
{
    IBase *i1 = instance1;
    IBase *i2 = instance2;
    i1->Func();
    i2->Func();
}

DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(a,b);

or

class SomeParam;
class IBase
{
public:
    virtual void Func()
    {
        cout << "Base func";
    }
};

class DerivedA : public IBase
{
public:
    void Func()
    {
        //do some custom stuff
        cout << "DerivedA func";
        IBase::Func();
    }
};

class DerivedB : public IBase
{
public:
    void Func()
    {
        //do some custom stuff
        cout << "DerivedB func";
        IBase::Func();
    }
};

//at somewhere else
void FuncCaller(IBase *instance1, IBase *instance2)
{
    IBase *i1 = instance1;
    IBase *i2 = instance2;
    i1->Func();
    i2->Func();
}

DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(a,b);

Solution 2

Your virtual function is not overridden.

Your supposedly "virtual" methods in the derived classes have different signatures. The method in the base class has one parameter, while the methods in the derived classes have no parameters. Because of this, the methods in the derived classes are completely unrelated to the base class method. They don't override the base class method. This is why the base class method is always called.

Solution 3

I've tried a copy of the code you posted on VS2008 and it works fine.

I can only suggest that your actual code is more like:

void FuncCaller(IBase instance)
{
    instance.Func();
}

void Funcs()
{
DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(*a);
FuncCaller(*b);
}

where FuncCaller slices the base part off the derived instances.

Solution 4

I found the reason:
The overriden virtual functions also must have a default parameter like Base's.like:

class DerivedB : public IBase
{
public:
    void Func(SomeParam* param=NULL)
    {
        //do some custom stuff
        cout << "DerivedB func";
        IBase::Func();
    }
};

Thanks for the answers guys.

Share:
20,465
Taz
Author by

Taz

Updated on February 24, 2020

Comments

  • Taz
    Taz about 4 years

    a more exact version of the code is:

    class SomeParam;
    class IBase
    {
    public:
        virtual void Func(SomeParam* param = NULL)
        {
            cout << "Base func";
        }
    };
    
    class DerivedA : public IBase
    {
    public:
        void Func()
        {
            //do some custom stuff
            cout << "DerivedA func";
            IBase::Func();
        }
    };
    
    class DerivedB : public IBase
    {
    public:
        void Func()
        {
            //do some custom stuff
            cout << "DerivedB func";
            IBase::Func();
        }
    };
    
    //at somewhere else
    void FuncCaller(IBase *instance1, IBase *instance2)
    {
        IBase *i1 = instance1;
        IBase *i2 = instance2;
        i1->Func();
        i2->Func();
    }
    
    DerivedA *a = new DerivedA;
    DerivedB *b = new DerivedB;
    FuncCaller(a,b);
    

    This gives me:
    "Base func"
    "Base func"