#c
#c
Вопрос:
Например, мы знаем, что следующий код будет выполняться как подробно:
#include <iostream>
class Base {
public:
virtual ~Base() {
std::cout << "Destroying base" << std::endl;
}
};
class Derived: public Base {
public:
~Derived() {
std::cout << "Destroying derived" << std::endl;
}
};
int main()
{
Base* p = new Derived();
delete p;
}
$ g --std=c 11 main.cc -o main; ./main
Destroying derived
Destroying base
Как это поведение реализуется компилятором? В ответе, вероятно, также потребуется рассказать о реализации vtable.
Высокоуровневый, простой для понимания ответ высоко ценится!
Комментарии:
1. Что вы имеете в виду под «как это реализовано»? Стандарт C определяет алгоритм, и компилятор просто следует ему.
2. Я не понимаю, какой ответ вы ищете. Существует спецификация C , и компилятор может реализовать ее так, как он хочет.
3. повторно — спасибо за ответ. Я не очень хорошо знаком со спецификацией C , и под «реализацией» я подразумеваю на уровне обсуждения как статического вывода, так и того, как динамически работает генерируемый код.
4. @Yksisarvinen это может быть, но они не вынуждены это делать, поэтому вы не можете быть уверены, если не проверите код каждого отдельного компилятора, и даже тогда он может измениться в любое время только для одного компилятора (маловероятно, но все же теоретически возможно). Я не настолько хорошо разбираюсь в реализациях компилятора, поэтому я бы не знал, как ответить на вопрос о конкретном, но ответ на более общий «как компиляторы это реализуют?» — это старое доброе «Это зависит».
5. Если вас действительно интересуют подробности, вот генерация кода Clang для деструктора класса
Ответ №1:
С точки зрения C конструкторы и деструкторы являются специальными функциями. Например, у них нет возвращаемых типов.
Типичный компилятор C , вероятно, все еще будет генерировать довольно нормальную функцию, по крайней мере, с его точки зрения. Это упрощает компоновщик. Но функция может содержать немного больше, чем просто ваш собственный код на C . Однако вы не можете получить адрес этой функции.
В этом конкретном случае компилятор, скорее всего, встроит вызов Base::~Base
в двоичный Derived::~Derived
файл . Это достаточно просто, нет виртуального или множественного наследования, усложняющего ситуацию.
Комментарии предполагают, что может быть задействована vtable. Очевидно, что для компиляторов, использующих vtables, им нужно будет поместить запись for Derived::~Derived
в эту таблицу, поскольку она virtual
. Вероятно, это будет та же обычная функция, которая содержит встроенный Base::~Base
вызов.