У меня проблема с выполнением виртуального вызова при использовании виртуального наследования.
Ниже приведен пример компилируемого кода, который демонстрирует код, который работает, когда не используется виртуальное наследование, а также код, который не будет работать навремя выполнения при использовании виртуального наследования.
BASE CLASSES Ниже приведены базовые calsses для обоих случаев:
#include <iostream>
class Base
{
public:
Base() { }
virtual ~Base() { }
// we need to make this bad call a good one!
virtual void bad_call(void* ptr)
{
Base* pThis = static_cast<Base*>(ptr);
pThis->f();
}
protected:
virtual void f() { std::cout << x << std::endl; }
int x = 0;
};
class Midle1 :
virtual public Base
{
public:
Midle1() { }
~Midle1() override { }
};
class Midle2 :
virtual public Base
{
public:
Midle2() { }
~Midle2() override { }
};
CASE 1 GOOD Вотслучай, который не использует виртуальное наследование (просто обычное наследование), где работают как виртуальные функции bad_call
, так и good_call
:
class GoodDerived :
public Base
{
public:
GoodDerived()
{
}
~GoodDerived() override
{
}
void good_call(void* ptr)
{
GoodDerived* pThis = static_cast<GoodDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
GoodDerived good_derived;
good_derived.good_call(&good_derived); // OK, will print 1
good_derived.bad_call(&good_derived); // OK, will print 2
std::cin.get();
return 0;
}
CASE 2 BAD И вот случайкоторый будет использовать виртуальное наследование, функция good_call
будет выполнена успешно, но bad_call
одна не удастся с «местом чтения нарушения доступа»
class BadDerived :
public Midle1,
public Midle2
{
public:
BadDerived() { }
~BadDerived() override { }
void good_call(void* ptr)
{
BadDerived* pThis = static_cast<BadDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
BadDerived bad_derived;
bad_derived.good_call(&bad_derived); // OK, will print 1
bad_derived.bad_call(&bad_derived); // ERROR: causes access violation
std::cin.get();
return 0;
}
ВОПРОС Этот второй случайпростой код, который продемонстрировал проблему, с которой я столкнулся прямо сейчас в своем проекте, и мне нужна помощь, чтобы решить, почему виртуальное наследование вызывает проблемы?
Почему первый случай работаетпросто отлично, а второй нет?