Стандарт не касается двоичной совместимости. Хотя это касается классов, и, «изменяя» определение класса с одного модуля перевода на другой, вы действительно вызываете неопределенное поведение.
Большинство компиляторов допускают ряд изменений без необходимости перекомпиляции, однако список невелик ... и для этого я бы сказал, что это невозможно, в зависимости от априорных знаний о производные классы .
Проблема, которую я предвижу, заключается в оптимизации, которую компиляторы обычно выполняют для виртуальных таблиц.
Когда вы создаете класс с виртуальными функциями, вы получаете виртуальную таблицу, которая выглядит так:
// B virtual table
0 - Offset to complete object
1 - RTTI
2 - func0
3 - func1
...
Чтобы получить некоторое пространство, собственные виртуальные функции производного класса обычно «добавляются»:
// D virtual table
Same as B
N+3 - func(N+1)
N+4 - func(N+2)
Таким образом, у объекта D
есть только один виртуальный указатель, который можно использовать как таковой, даже если тип является (статически) a B
(через указатель или ссылку).
Однако, если бы вы расширили B
без перекомпиляции D
, то это было бы просто крахом, поскольку при вызове функции N+1
для B
вы бы вместо этого вызвали функцию N+1
для D
который, вероятно, даже не имел бы таких же аргументов ... ау!
Однако это можно сделать, если вы знаете , тогда ни один производный класс не добавит ни одной своей виртуальной функции.