переопределенная виртуальная функция не вызывается - PullRequest
1 голос
/ 23 февраля 2010

более точная версия кода:

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);

Это дает мне:
«Базовый функционал»
«Базовый функционал»

Ответы [ 4 ]

9 голосов
/ 23 февраля 2010

Похоже, вы предоставили упрощенную версию своего кода, чтобы сделать его более читабельным, но вы случайно упростили его.

Наиболее вероятные причины вашего поведения:

  • Нарезка на FuncCaller() (подробности см. В ответе Квамраны)
  • Неправильное переопределение, например, создание функции производного класса const, в то время как функция базового класса не const

РЕДАКТИРОВАТЬ: После прочтения отредактированного вопроса, это явно вторая причина. Вы не переопределяете функцию базового класса, но скрываете ее в производных классах с новым определением. Вам необходимо сохранить точно такую ​​же сигнатуру (ковариация здесь не применяется, так как функция возвращает void) в производных классах. В коде вам нужно сделать либо:

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);

или

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);
2 голосов
/ 23 февраля 2010

Ваша виртуальная функция не переопределена.

Ваши предположительно "виртуальные" методы в производных классах имеют разные подписи. Метод в базовом классе имеет один параметр, в то время как методы в производных классах не имеют параметров. Из-за этого методы в производных классах совершенно не связаны с методом базового класса. Они не переопределяют метод базового класса. Вот почему метод базового класса всегда вызывается.

1 голос
/ 23 февраля 2010

Я нашел причину:
Переопределенные виртуальные функции также должны иметь параметр по умолчанию, например Base's.like:

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

Спасибо за ответы, ребята.

1 голос
/ 23 февраля 2010

Я попробовал копию кода, который вы разместили на VS2008, и он отлично работает.

Я могу только предположить, что ваш реальный код больше похож на:

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

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

, где FuncCaller вырезает базовую часть из производных экземпляров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...