перекомпилировать после изменения базового класса - PullRequest
1 голос
/ 08 февраля 2012

В частности, работа большинства реализаций C ++ подразумевает, что изменение размера базового класса требует перекомпиляции всех производные классы.

Это утверждение из книги Страуструпа. Итак, если базовый класс находится в .so файле, и мы просто меняем реализацию функции-члена, то означает ли это, что нам не нужно перекомпилировать мою программу, связанную с этим общим объектом?

Ответы [ 3 ]

3 голосов
/ 08 февраля 2012

Формально, если вы не перекомпилируете, вы нарушаете правило единого определения и получаете неопределенное поведение.

Практически, пока изменяемая вами функция-член нигде не встроена и вы не меняете сигнатуру, вы, вероятно, сохраняете двоичную совместимость. На большинстве платформ. Если вам повезет, в документации по вашей платформе есть такая гарантия.

0 голосов
/ 08 февраля 2012

Если это просто реализация, она должна работать нормально. Вот и вся концепция Windows DLL. Добавление или удаление интерфейсов не приведет к изменению размера класса (если вы не вводите новую виртуальную функцию), но в значительной степени способ, которым функции, изложенные в памяти, могут быть изменены. Поэтому перекомпиляция необходима, если вы используете новую функцию. С другой стороны, большинство современных компиляторов достаточно умны, чтобы идентифицировать соответствующие изменения из-за простой модификации в заголовочных файлах.

0 голосов
/ 08 февраля 2012

Я верю, что ваше понимание верно. Простое изменение тела функции-члена не меняет объем пространства, требуемого для экземпляра этого объекта. Код не хранится «в» экземпляре объекта; только данные.

Когда класс компилируется, ссылки на поля данных элемента просто смещаются от начала данных этого объекта. А данные производных классов обычно помещаются после данных базового класса. Поэтому, если вы добавите поле в базовый класс, все правильные смещения для данных производного класса будут изменены, что означает, что базовый класс нуждается в перекомпиляции, чтобы указывать на новые (правильные) смещения.

До

class Foo {
    int a;              // offset 0 (assuming no vtable)
}

class Bar : public Foo {
    int b;              // offset 4
}

Bar bar;  bar.b = 7;    // sets the 32-bit value at this+4 to 7

* После 1013 *

class Foo {
    int a;              // offset 0
    int c;              // offset 4
}

class Bar : public Foo {
    int b;              // offset 8
}

Bar b;   bar.b = 7;     // Without recompiling: sets the 32-bit value at this+4
                        //   which is actually where Foo.a is stored!
                        // With recompiling: sets the 32-bit value at this+8
...