преобразование указателя на базовый объект в указатель производного класса

Меня смутило преобразование указателя на объект базового класса в указатель производного класса.
Пожалуйста, проверьте следующий код:

derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();

Результат:

  • Я виртуальная функция в базе.
  • Я функция в производном классе.
  • Может кто-нибудь помочь мне объяснить, почему d1->print() print «Я виртуальная функция в базе.»

    #include <iostream>
    using namespace std;
    
    class base
    {
    public:
    virtual void print()
    {
    cout << "I'm a virtual function in base." << endl;
    }
    };
    
    class derivate_class : public  base
    {
    public:
    void print()
    {
    cout << "I rewrite the virtual function in base." << endl;
    }
    
    void print1()
    {
    cout << "I'm a function in derivate class." << endl;
    }
    };
    
    int main()
    {
    base* b = new base();
    derivate_class *d = new derivate_class();
    b->print();
    d->print1();
    base* cb = b;
    b = d;
    b->print();
    cout << "*********************" << endl;
    
    derivate_class *d1 = (derivate_class*)cb;
    d1->print();
    d1->print1();
    
    system("pause");
    return 0;
    }
    

    0

    Решение

    Это UB, так что все может случиться.

    Но вот объяснение: d1 на самом деле не указывает на derivate_class, но к base,

    base* b = new base();
    //...
    base* cb = b;
    derivate_class *d1 = (derivate_class*)cb;
    d1->print();
    d1->print1();
    

    Вызов разрешается динамически, потому что это через указатель и метод virtual,

    print1 не virtual поэтому вызов разрешается статически. print однако virtual, поэтому реализация в наиболее производном типе называется. Но самый производный тип на самом деле base в этом случае.

    Под капотом, метод print ищется в таблице виртуальных функций, в которой vfptr cb указывает на. поскольку cv это baseстол будет из base, который содержит функцию print с base::print реализация. Вот почему эта функция вызывается.

    2

    Другие решения

    d1 является указателем производного_класса, но данные, на которые он фактически указывает (cb), имеют тип base. Поскольку print () является виртуальным, вызов разрешается динамически, и поэтому он найдет реализацию базы в таблице виртуальных функций, а не в производном_классе.

    0

    По вопросам рекламы ammmcru@yandex.ru
    Adblock
    detector