«Действительный» - это конкретный термин применительно к указателям. Указатели данных действительны, когда они указывают на объект или NULL
; указатели на функции действительны, когда они указывают на функцию или NULL
, а указатели на элементы действительны, когда указатель на элемент или NULL
.
Тем не менее, из вашего вопроса о фактических результатах я могу сделать вывод, что вы хотели спросить что-то еще. Давайте посмотрим на вашу vmember
функцию - или я должен сказать функции? Очевидно, есть два функциональных тела. Вы могли бы сделать только один производный виртуальным, так что это также подтверждает, что на самом деле есть две vmember
функции, которые обе оказываются виртуальными.
Теперь возникает вопрос, выбирает ли адрес функции-члена уже действительную функцию. Ваши реализации показывают, что они этого не делают, и что это происходит только тогда, когда указатель действительно разыменовывается.
Причина, по которой должен работать таким образом, тривиальна. Взятие адреса функции-члена не затрагивает фактический объект, то, что потребуется для разрешения виртуального вызова. Позвольте мне показать вам:
namespace {
void (A::*test)() = &A::vmember;
A a;
B b;
(a.*test)();
(b.*test)();
}
Когда мы инициализируем test
, объект типа A
или B
вообще не существует, но возможно взять адрес &A::vmember
. Этот тот же самый указатель члена может тогда использоваться с двумя различными объектами. Что это может произвести, кроме "In A :: vmember () \ n" и "In B :: vmember () \ n"?