Ответ 1
Что означает двусмысленность?
Компилятор жалуется на неоднозначные вызовы, когда он не может решить, какую функцию вызывать с учетом контекста. Итак, чтобы понять жалобы, вы должны проверить, какие могут быть возможные двусмысленности.
Почему компилятор жалуется на неоднозначный вызов нестатической версии increment(), но удовлетворяет статическому?
По определению функция static
класса не зависит от какого-либо экземпляра класса. Это подчеркивается тем фактом, что вы могли бы назвать его A::increment()
(см., Нет экземпляра).
Проблема наследования алмазов заключается не в том, что компилятор не знает, какой код выполнить, он не знает, какой this
должен предоставить (в вашем D
объекте есть два A
, один из которых содержит в B
и один в C
).
Когда вы используете функцию static
A
, не пропускается неявный this
, поэтому нет проблемы; если вы попытаетесь использовать функцию не static
, тогда компилятор не может решить, должен ли this
указывать на A
в B
или в C
, это неоднозначно.
Если я добавлю другую функцию increment() в B или C, компилятор тоже будет жаловаться, даже объявлен как статический. Почему?
В этот момент компилятор может выбрать между B::increment()
и C::increment()
, который он должен выбрать? Это двусмысленно.
Когда у вас есть линейная иерархия, она вызывает "ближайший" к ней (который скрывает их далее по дереву наследования), но здесь B
и C
являются двумя независимыми ветвями и нет "лучшей" ветки.
Примечание: даже если B
не реализует increment
, так как A
вы можете вызвать B::increment()
, который фактически вызывает A::increment()
. То же самое касается C
.