Я хочу понять причину вывода следующих программ на C++, включающих виртуальные функции. Также объясните, как таблица указателей функций и таблица виртуальных указателей, содержащая ссылки на таблицы указателей функций, будут генерироваться в следующих двух случаях и как вызов разрешается во время выполнения.
/******* 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;
}
Вы также можете проконсультироваться с этот список. Ничто не сравнится с хорошей проверенной книгой, которая поможет разобраться в таком сложном языке, как C++.
@ user4581301 Почему вы не считаете это ответом?
@Yunnosch Слишком похоже на опечатку. Если бы это было не так, для будущих программистов не было бы большой ценности в «Идентификаторы должны совпадать». Если вы не знаете, что по таймеру вы достигли переполнения стека, ваш справочный материал в лучшем случае сомнительный.
@ user4581301 В приведенном выше фрагменте кода, указанном в вопросе, нет опечатки. Мне задали этот вопрос в интервью Arcesium, и я не смог ответить. Мне отказали, и первое, что я сделал после этого, — разместил этот вопрос здесь. Прошло 2 года, и в настоящее время я работаю в материнской компании Arcesium D.E. Шоу, как разработчик C++ (SDE-II). Принятый ответ и все комментарии теперь имеют для меня смысл.
Согласен, я не думаю, что прочитал вопрос достаточно внимательно, чтобы понять, что вы на самом деле спрашивали.
Здесь — довольно хорошее объяснение виртуальных функций и виртуальных таблиц.
Every class that uses virtual functions (or is derived from a class that uses virtual functions) is given its own virtual table
Each entry in this table is simply a function pointer that points to the most-derived function accessible by that class.
Это в значительной степени отвечает на ваши вопросы.
В первом примере самая производная функция, доступная c
, — это функция Car
foo
.
А во втором это Bmw
foo
. Здесь хоть вы и не написали virtual
перед foo
(что не очень хороший стиль кодирования) в Bmw
, его виртуальность унаследована от Car
.
Обновлено: Как было правильно сказано в комментарии, vtables не являются частью стандарта. См. эта ссылка для более формального объяснения.
For every virtual function, there is the final overrider, which is executed when a virtual function call is made. A virtual member function vf of a base class Base is the final overrider unless the derived class declares or inherits (through multiple inheritance) another function that overrides vf.
Примечание: C++ не требует использования VTables. VTables, безусловно, являются наиболее распространенной реализацией, потому что они выполняют работу прямым и относительно простым способом реализации, так что это то, что вы, скорее всего, увидите. Тем временем в секретных лабораториях по всему миру ведущие ученые работают над альтернативами, всегда ища лучшее решение.
Спасибо, да, только что предоставил этот ответ, поскольку вопрос был конкретно о vtable. Отредактировано.
foo1
неfoo
. Вы можете найтиoverride
полезным