Виртуальное переопределение и двоичная совместимость - PullRequest
2 голосов
/ 08 сентября 2011

У меня есть библиотека, которую можно скомпилировать как общую библиотеку (или DLL в Windows). У него есть класс, производный от другого класса в другой библиотеке. Базовый класс имеет несколько виртуальных методов, и мой класс переопределяет некоторые из них. Например:

class Base {
public:
    virtual void method1();
    virtual void method2();
    virtual void method3();
};

class Derived: public Base {
public:
    virtual void method2();
};

Теперь я понял, что один из виртуальных методов не совсем подходит для моего класса. В настоящее время он не переопределяет этот метод, поэтому я хочу переопределить его, чтобы исправить его поведение:

class Derived: public Base {
public:
    virtual void method2();
    virtual void method3();
};

Это нарушит бинарную совместимость со старыми версиями моей библиотеки?

Насколько я понимаю, это отличается от простого добавления виртуальных функций, так как количество и порядок виртуальных методов в vtable остается неизменным. Разница лишь в том, что конкретная запись в vtable для моего класса теперь будет содержать другое значение. Это правильно?

Я также совершенно уверен, что ни одно из приложений, в настоящее время использующих мою библиотеку, не использует этот метод, поскольку он полностью сломан и никогда не работает. Так что я не беспокоюсь о том, чтобы сломать существующие вызовы реализации базового метода. Я просто хочу убедиться, что больше ничего не сломаю.

Ответы [ 3 ]

3 голосов
/ 08 сентября 2011

Поскольку вы говорите о DLL, я предполагаю, что это C ++ в Visual Studio / Windows.Добавление переопределения не нарушит двоичную совместимость, поскольку размер vtable не изменяется.Однако это может привести к нежелательным результатам, если вы не перекомпилируете весь код, который создает новые экземпляры Derived.Это связано с тем, что vtable инициализируется источником создания экземпляра, а не источником класса, реализующего Derived.

0 голосов
/ 08 сентября 2011

Библиотека, к которой относится ваш производный класс (в который добавлен новый виртуальный метод), * ​​1001 * не обязательно будет двоичной (ABI) совместимой со старой версией библиотеки. Это связано с тем, что вы не можете контролировать, как vtable генерируется компилятором при добавлении переопределенного виртуального метода.

0 голосов
/ 08 сентября 2011

Если я правильно понял, у вас есть базовый класс в Dll1 и ваш производный класс в Dll2. Если это так, то изменение, которое вы описываете, не влияет на Dll1. Предполагая, что вы установите обновленный Dll2, ваше приложение будет переключаться на вызов Derived :: method3 () всякий раз, когда вы будете обращаться к экземплярам Derived через указатели или ссылки на Base.

...