По ошибке я написал что-то глупое, что к моему удивлению сработало.
class A
{ public:
void print()
{
std::cout << "You can't/won't see me !!!" << std::endl;
}
A* get_me_the_current_object()
{
return this;
}
};
int main()
{
A* abc = dynamic_cast<A*>(abc);
abc->print();
}
Вот, A* abc = dynamic_cast<A*>(abc)
Я делаю dynamic_cast для указателя, который не объявлен. Но это работает, поэтому я предположил, что приведенное выше утверждение нарушается как:
A* abc;
abc = dynamic_cast<A*>(abc);
и, следовательно, это работает. Однако, попробовав несколько более странных сценариев, таких как:
A* abc;
abc->print();
и далее
A* abc = abc->get_me_the_current_object();
abc->print();
Я был ошеломлен, глядя на то, как эти примеры работали, и отображение было сделано.
Может кто-нибудь рассказать, как это работает? Заранее спасибо.
Вы сделали общую ошибку, считая, что неопределенное поведение и ошибки в C ++ означают, что вы должны ожидать резкого сбоя или возгорания вашего компьютера. Иногда ничего не происходит. Это не означает, что код «работает», потому что в нем все еще есть ошибка, просто симптомы не проявляются … еще.
Но это работает, поэтому я предположил, что приведенное выше утверждение нарушается как:
Да, все, что вы делаете, это конвертируете неинициализированный указатель в один и тот же тип, то есть конвертация не требуется, поэтому компилятор ничего не делает. Ваш указатель все еще того же типа и все еще неинициализирован.
Это похоже на это:
int i = i;
Это верно в соответствии с грамматикой C ++, потому что i
в данный момент находится в области видимости, но не определен, поскольку копирует неинициализированный объект. Это вряд ли на самом деле подожжет ваш компьютер, хотя, кажется, «работает».
Может кто-нибудь рассказать, как это работает?
Технически вы разыменовываете недействительный указатель, который является неопределенным поведением, но поскольку ваши функции-члены фактически не используют никаких членов объекта, недействительный this
указатель не разыменовывается, поэтому код «работает» (или, по крайней мере, отображается как.)
Это похоже на:
void function(A* that)
{
std::cout << "Hello, world!\n";
}
A* p;
function(p);
Поскольку that
указатель не используется (как this
указатель не используется в ваших функциях-членах) это не обязательно приводит к сбою, хотя это может происходить в реализациях, где даже копирование неинициализированного указателя может вызвать аппаратную ошибку. В вашем примере кажется, что ваш компилятор не нуждается в разыменовании abc
вызвать нестатическую функцию-член и передать ее как скрытую this
Параметр не вызывает аппаратного сбоя, но поведение по-прежнему не определено, даже если он не дает сбоя очевидным образом, например, в случае segfault.
abc
неинициализирован и указывает на неопределенное место в памяти, но ваши методы ничего не читают из *this
чтобы они не разбились.
Тот факт, что они не потерпят крах, почти наверняка является поведением, определяемым реализацией.