Подтвердить что ты не робот

Даустаун в алмазной иерархии

Почему static_cast не может отключиться от виртуальной базы?

struct A {};
struct B : public virtual A {};
struct C : public virtual A {};
struct D : public B, public C {};

int main()
{
  D d;
  A& a = d;
  D* p = static_cast<D*>(&a); //error
}  

g++ 4.5 говорит:

 error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’

Решение состоит в использовании dynamic_cast? но почему. Что такое рациональное?

- изменить -
Очень хорошие ответы ниже. В ответах подробно не указано, каким образом субобъекты и vtables могут быть заказаны. Следующая статья дает хорошие примеры для gcc:
http://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting

4b9b3361

Ответ 1

Потому что, если объект действительно имеет тип E (полученный из D), расположение субобъекта A относительно подобъекта D может быть иным, чем если объект фактически D.

На самом деле это происходит, если вы считаете, что вместо кастования от A до C. Когда вы выделяете C, он должен содержать экземпляр A и он живет с некоторым определенным смещением. Но когда вы назначаете D, подобъект C ссылается на экземпляр A, который поставляется с B, поэтому смещение отличается.

Ответ 2

Очевидным ответом является то, что стандарт говорит так. мотивация в этом стандарте заключается в том, что static_cast должен быть близок к тривиальному, самое большее, простое дополнение или вычитание константы в указатель. Где спустит для виртуальной базы потребуется более сложный код: возможно, даже с дополнительной записью в vtable где-нибудь. (Это требует нечто большее, чем константы, поскольку положение D относительно A может измениться, если есть дальнейший вывод.) Преобразование очевидно выполнимо, поскольку, когда вы звоните виртуальная функция на A*, и функция реализована в D, компилятор должен это сделать, но дополнительные служебные данные были считается неуместным для static_cast. (Предположительно, единственной причиной использования static_cast в таких случаях является оптимизации, поскольку dynamic_cast обычно является предпочтительным решение. Поэтому, когда static_cast, вероятно, будет таким же дорогим, как dynamic_cast в любом случае, зачем его поддерживать.)