Ответ 1
Нарушенное здесь правило документировано в С++ 03 3.10/15 [basic.lval], в котором указано, что неформально упоминается как "правило строгого сглаживания"
Если программа пытается получить доступ к сохраненному значению объекта через значение l, отличного от одного из следующих типов, поведение undefined:
динамический тип объекта,
cv-квалифицированная версия динамического типа объекта,
тип, который является подписанным или неподписанным типом, соответствующим динамическому типу объекта,
тип, который является подписанным или неподписанным типом, соответствующим квитанционной версии динамического типа объекта,
совокупность или тип объединения, который включает один из вышеупомянутых типов среди его членов (включая рекурсивно, член субагрегата или содержащегося объединения),
тип, который является (возможно, cv-квалифицированным) типом базового класса динамического типа объекта,
a char или неподписанный char тип.
Короче говоря, при заданном объекте вы можете получить доступ к этому объекту только через выражение, имеющее один из типов в списке. Для объекта класса, который не имеет базовых классов, например std::vector<T>
, в основном вы ограничены типами, указанными в первой, второй и последней палитрах.
std::vector<Base*>
и std::vector<Derived*>
являются полностью несвязанными типами, и вы не можете использовать объект типа std::vector<Base*>
, как если бы это был std::vector<Derived*>
. Компилятор может делать всевозможные вещи, если вы нарушаете это правило, в том числе:
-
выполнять разные оптимизации на одном, а не на другом, или
-
выложите внутренние элементы одного по-другому или
-
выполнить оптимизацию, предполагая, что a
std::vector<Base*>*
никогда не может ссылаться на тот же объект, что иstd::vector<Derived*>*
-
используйте проверки времени выполнения, чтобы убедиться, что вы не нарушаете правило строгого псевдонима
[Он также может не выполнять ничего из этого, и он может "работать", но нет гарантии, что он "сработает", и если вы измените компиляторы или версии компилятора или параметры компиляции, все это может остановить "работу". Здесь я использую цитаты с испугом.: -)]
Даже если у вас был только Base*[N]
, вы не могли использовать этот массив, как если бы это был Derived*[N]
(хотя в этом случае использование, вероятно, было бы более безопасным, где "безопаснее" означает "все еще undefined, но менее вероятно, чтобы вы попали в беду).