Я собираюсь немного упростить пример:
data_impl a(3), b(7);
data &ra(a);
data &rb(b);
std::cout << ra.get_value() << std::endl;
ra = rb; // [1]
std::cout << ra.get_value() << std::endl;
Теперь с этим упрощенным кодом легче рассуждать о программе.Вы получаете ссылку ra
на подобъект a
, но ссылка имеет тип data
, а не data_impl
.Аналогично с rb
и b
.В строке, помеченной [1], вы выполняете присваивание от rb
до ra
, статический тип двух аргументов выражения - data
, и это означает, что независимо от того, к какому реальному объекту они относятсяв том, что эта конкретная строка назначает только подобъект data
.Это называется нарезка .
То есть [1] устанавливает подобъект data
для a
таким же, как подобъект data
для b
.Поскольку data
не содержит никаких фактических данных, в результате a
остается неизменным.
В качестве более наглядного примера вы можете добавить поле к data
и проверить, что выражение действительно изменяетэто поле в a
, даже если оно не модифицировало поля в производных классах.
Затем вы можете вручную попробовать агрегат operator=
в качестве виртуальной функции и проверить, что вы можете получить ожидаемый результат, нореализация будет немного более запутанной, поскольку в C ++ нет ковариантных аргументов для функций-членов, что означает, что подпись operator=
на всех уровнях будет принимать (const) ссылку на data
, и вы будете вынужденыdowncast (убедитесь, что приведение выполнено успешно), а затем выполните назначение ...