«Частные члены не наследуются» - это ложная предпосылка, это не Java.
Доступ пользователя в C ++ был разработан таким образом, что если вы заменяете любое личное: public :, поведение программы не изменится.
Из-за этого, поиск имени, который возникает здесь, когда компилятор встречает имя «display» в d.display (), сначала находит все функции-члены в d с этим именем (их два), затем находит наилучшее совпадение (сбой здесь), и только затем проверяет, недоступно ли это из-за правил доступа членов.