Reguła naruszone tutaj jest udokumentowana w C++ 03 3,10/15 [basic.lval], która określa, co jest określane jako „nieformalnie ścisłe reguły aliasing”
Jeśli program próbuje uzyskać dostęp do zapisana wartość przedmiotu poprzez lwartością z innych niż jeden z następujących typów zachowanie jest niezdefiniowane:
dynamiczny rodzaj obiektu,
wersja cv wykwalifikowany dynamicznego typu obiektu,
typ, który jest podpisany lub typ unsigned odpowiadający dynamicznego typu obiektu,
typ, który jest podpisany lub niepodpisane typ odpowiadający CV- wykwalifikowany wersja dynamicznego typu obiektu,
agregatem lub unia typ, który zawiera jeden z wyżej wymienionych typów wśród swoich członków (w tym rekurencyjnie, członek subaggregate lub zawartej unii),
typ, który jest (możliwe bly cv-qualified) typ klasy podstawowej dynamicznego typu obiektu,
char lub unsigned char type.
Krótko mówiąc, biorąc pod uwagę przedmiot, są dozwolone tylko w celu uzyskania dostępu do tego obiektu za pomocą wyrażenia, które ma jeden z typów na liście. W przypadku obiektu typu klasowego, który nie ma klas podstawowych, takich jak std::vector<T>
, w zasadzie ogranicza się do typów wymienionych w punktach pierwszym, drugim i ostatnim.
std::vector<Base*>
i std::vector<Derived*>
są zupełnie niepowiązanych typy i nie można korzystać z obiektu typu std::vector<Base*>
jakby to była std::vector<Derived*>
.Kompilator może zrobić różne rzeczy, jeśli narusza tę zasadę, w tym:
wykonywać różne optymalizacje na jednym niż z drugiej, albo
rozplanować wewnętrzne członków jednej inaczej lub
wykonywać optymalizacje zakładając, że std::vector<Base*>*
nie może odnosić się do tego samego obiektu jako std::vector<Derived*>*
kontroli użycie wykonawczych zapewniających t Kapelusz nie łamią ścisłego aliasingu regułę
[Może to również zrobić żadnej z tych rzeczy, a to może „pracować”, ale nie ma gwarancji, że będzie to „praca” i jeśli zmienisz kompilatory lub kompilator wersje lub ustawienia kompilacji, może przestać działać. Używam tutaj przerażających cytatów z jakiegoś powodu. :-)]
Nawet jeśli po prostu miałeś Base*[N]
, nie możesz użyć tej tablicy tak, jakby była to Derived*[N]
(chociaż w tym przypadku użycie byłoby bezpieczniejsze, gdzie "bezpieczniejsze" oznacza "wciąż niezdefiniowane, ale mniej prawdopodobne, aby dostać się w kłopoty).
Użycie reinterpret_cast <>() po tym punkcie nic nie jest zdefiniowane. To może zadziałać, ale twoja lista warunków jest okropnie krótka. Dodałbym jeszcze kilka wstępnych warunków. sizeof (A) == sizeof (B); Ani A, ani B nie mogą zawierać żadnych typów funkcji wirtualnych. Ani A, ani B, ani żaden potomek umieszczony w tablicy nie może używać dziedziczenia wielokrotnego. –
Odpowiedź na niecertyfikowaną C++ polega na tym, że nie jest ona bezpieczna dla typów.Jeśli dodasz 'A' do foo, masz test w stanie niepoprawnym, ponieważ gwarantuje to, że wszystkie elementy są typu' B'. A C# też tego nie obsługuje. C# obsługuje tylko dla ogólnych parametrów, które są używane w bezpieczny sposób (tylko wejściowe lub wyjściowe) i tylko w interfejsach i delegatach. Java obsługuje go, ponieważ dodaje kontrole czasu wykonywania i wewnętrznie działa na obiekcie klasy podstawowej. – CodesInChaos
To pytanie wygląda podobnie do http://stackoverflow.com/questions/842387/how-do-i-dynamically-cast-between-vectors-ofpointpoints – Nekuromento