C ++ неожиданный вызов функции унаследованных классов - PullRequest
1 голос
/ 09 января 2020

Я сделал следующие 3 класса:

struct Parent1
{
    virtual void f()
    {
        cout << "\nParent1::f";
    }
};
struct Parent2
{
    virtual void g()
    {
        cout << "\nParent2::g";
    }
    virtual void z()
    {
        cout << "\nParent2::z";
    }
};
struct Child : public Parent1, public Parent2
{
    virtual void h()
    {
        cout << "\nChild::h";
    }
};

В основном, когда я вызываю функцию z из Parent2, она вместо этого вызывает функцию h дочернего класса. Почему так происходит? Ниже приводится функция main:

int main()
{
    Child obj;
    Parent2 * p2 = (Parent2*)(Parent1*)&obj;
    p2->z();
    return 0;
}

1 Ответ

8 голосов
/ 09 января 2020

Первое явное преобразование из &obj, то есть Child* в Parent1*, является повышением. Результат будет указывать на подобъект базового класса. Следующее явное преобразование из Parent1* в Parent2*. Поскольку эти классы не связаны напрямую, это приведение к реинтерпретации. Но типы не являются взаимозаменяемыми по указателю, поэтому при вызове функции через переинтерпретированный указатель поведение программы не определено.

Вам следует избегать использования приведения в стиле C, чтобы предотвратить подобные ошибки. В этом случае явное приведение не требуется вообще. Это работает правильно:

Parent2 * p2 = &obj;

И никогда не переинтерпретируйте указатели, если вы не знаете, что это значит и что это нормально.

...