Я пытаюсь добавить новые функции в существующую библиотеку. Мне нужно будет добавить новые данные в иерархию классов, чтобы у корневого класса были доступ к ним. Любой человек должен иметь возможность получать эти данные, только подклассы могли бы установить его (т. Е. Публичный геттер и защищенный сеттер).Расширение класса и поддержка двоичной обратной совместимости
Для обеспечения обратной совместимости, я знаю, что я не должен делать любой из следующих (список включает только действия, имеющие отношение к моей проблеме):
- Добавить или удалить виртуальные функции
- Добавить или удалить переменные-члены
- Изменение типа существующего переменной-члена
- Изменить подпись существующей функции
Я могу представить два способа добавления этих данных в иерархию: добавление новой переменной-члена в корневой класс или добавление чистых виртуальных функций доступа (чтобы данные могли храниться в подклассах). Однако, чтобы поддерживать отсталую совместимость, я не могу сделать ни одного из них.
В библиотеке широко используется pimpl идиома, но, к сожалению, класс корня, который я должен изменить, не используйте эту идиому. Однако подклассы используют эту идиому.
Теперь только решение, о котором я могу думать, моделирует переменную-член со статической хэш-картой. Поэтому я мог бы создать статическую хэш-карту, сохранить в ней этот новый элемент и реализовать для нее статические аксессоры. Нечто подобное (в псевдо C++):
class NewData {...};
class BaseClass
{
protected:
static setNewData(BaseClass* instance, NewData* data)
{
m_mapNewData[instance] = data;
}
static NewData* getNewData(BaseClass* instance)
{
return m_mapNewData[instance];
}
private:
static HashMap<BaseClass*, NewData*> m_mapNewData;
};
class DerivedClass : public BaseClass
{
void doSomething()
{
BaseClass::setNewData(this, new NewData());
}
};
class Outside
{
void doActions(BaseClass* action)
{
NewData* data = BaseClass::getNewData(action);
...
}
};
Теперь, в то время как это решение может работать, я считаю, это очень некрасиво (конечно, я мог бы также добавить нестатические функции доступа, но это не устранило бы уродства) ,
Есть ли другие решения?
Спасибо.
Разве вы не добавляете `m_mapNewData` в класс root здесь, о котором вы сами говорили, это не так? – Jon 2010-12-16 10:22:30
Вы уверены, что вам нужна * двойная * обратная совместимость? Я считаю это довольно странным в контексте класса C++, тем более для класса * base *. – 2010-12-16 10:26:08
@Jon: Поскольку это * статическая переменная-член, я думаю, что она не нарушит двоичную обратную совместимость, так как (к моему недоумению) она не меняет размер или макет класса. @Martin: Да, мне нужна * двоичная * обратная совместимость. Это широко используемая библиотека с открытым исходным кодом, и мы хотим, чтобы все существующие приложения продолжали работать после изменений. – user544511 2010-12-16 10:44:45