Это полностью зависит от компилятора и неопределенное поведение в соответствии со стандартом. Вы не должны полагаться на это.
Вызов func2()
успешен, потому что точный метод для вызова известен во время компиляции (вызов не виртуальный), а сам метод не разыменовывает этот указатель. Так недействительно это нормально.
ptr->func1(); // This works
, потому что компилятору дано указание вернуть ссылку на член класса. Для этого он просто добавляет смещение члена к недопустимому значению этого указателя, и это создает еще один недопустимый указатель (ссылка, которая почти такая же).
int crashere=ptr->func1();// Crashes here
потому что теперь компилятору дано указание получить значение по этой недействительной ссылке, и это привело к сбою программы.