Добро пожаловать в замечательный мир Неопределенное поведение ! Согласно C ++ spe c, поведение этой проблемы не определено, поэтому то, что вы видите, может работать в вашей системе, но может sh в других или наоборот.
Практически говоря, то, что здесь происходит, вероятно, является артефактом того, как компилятор генерирует код для функций-членов. Как правило, функция-член, которая выглядит следующим образом:
void doSomething() {
cout << "Hello!" << endl;
}
, вероятно, будет скомпилирована, как если бы это была свободная функция, подобная этой:
void Base_doSomething(Base* this) {
cout << "Hello!" << endl;
}
В этом смысле, когда вы пишете
bf->doSomething();
компилятор обрабатывает его так, как будто вы написали
Base_doSomething(bf);
, и ничего плохого не происходит, потому что Base_doSomething
не ссылается на указатель this
, где все случаются плохие вещи.
Так вот, это очень хрупко. Если вы попытаетесь прочитать какой-либо элемент данных типа Base
, этот код обработает sh, потому что тогда вы читаете из неверного указателя. Точно так же, если бы doSomething
была функцией virtual
, вы получили бы cra sh, потому что для вызова виртуальной функции (обычно) требуется чтение из объекта-получателя, чтобы найти vtable , чтобы определить, какая функция вызвать, и висячий указатель приведет к плохому доступу к памяти.
Итак, подведем итог:
- Этот код приводит к неопределенному поведению, поэтому конкретное поведение вы не гарантируется, что видение будет работать или работать на разных платформах.
- Хотя синтаксически
bp->doSomething()
выглядит как разыменование указателя, на самом деле оно может не включать разыменование указателя. - Функции-члены обычно компилируются как свободные функции с указателем «неявный
this
», переданным в качестве первого аргумента. - Виртуальные функции работают не так, как это, поэтому вы ожидаете увидеть другое поведение там.
Надеюсь, это поможет!