Объяснение вывода кода C ++, включающего виртуальную функцию - PullRequest
1 голос
/ 10 апреля 2019

Я хочу понять причину вывода следующих программ на C ++, использующих виртуальные функции.Пожалуйста, объясните, как таблица указателей функций и таблица виртуальных указателей, содержащие ссылки на таблицы указателей функций, будут генерироваться в следующих 2 случаях и как вызов разрешается во время выполнения.

/******* PROGRAM 1 *******/
#include <iostream>
using namespace std;

class Car {
    public:
    virtual void foo() {
        cout<<"Car"<<endl;
    }
};

class Bmw: public Car {
    public:
    void foo1() {
        cout<<"Bmw"<<endl;
    }
};

int main() {
        Car *c = new Bmw(); 

        c->foo();           // gives output Car even though foo() 
                            //function does not exist in BMS class. 

        return 0;
}

/******* PROGRAM 2 *******/
#include<iostream>
using namespace std;

class Car {
    public:
    virtual void foo() {
        cout<<"Car"<<endl;
    }
};

class Bmw: public Car {
    public:
    void foo() {
        cout<<"Bmw"<<endl;
    }
};

class Bmw7: public Bmw {
    public:
    void foo1(){
        cout<<"Bmw7"<<endl;
    }
};

int main() {
    Car *c = new Bmw7();

    c->foo();       //gives output Bmw. Why output is not Car ??
    return 0;
}

1 Ответ

0 голосов
/ 10 апреля 2019

Здесь - довольно хорошее объяснение виртуальных функций и виртуальных таблиц.

Дан каждый класс, который использует виртуальные функции (или является производным от класса, который использует виртуальные функции)собственная виртуальная таблица

Каждая запись в этой таблице - просто указатель на функцию, которая указывает на наиболее производную функцию, доступную для этого класса.

Это в значительной степени отвечает на ваши вопросы.В первом примере наиболее производная функция, доступная c, - это Car 's foo.А во втором это Bmw х foo.Здесь, даже если вы не написали virtual перед foo (что не очень хороший стиль кодирования) в Bmw, его виртуальность наследуется от Car.

.РЕДАКТИРОВАТЬ: Как было правильно указано в комментарии, vtables не являются частью стандарта.См. эту ссылку для более формального объяснения.

Для каждой виртуальной функции существует заключительный переопределитель, который выполняется при выполнении вызова виртуальной функции.Виртуальная функция-член vf базового класса Base является окончательным переопределением, если производный класс не объявляет или не наследует (посредством множественного наследования) другую функцию, которая переопределяет vf.

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