Расширение класса и поддержание обратной совместимости двоичных файлов

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

Я знаю, что для обеспечения обратной совместимости я не должен делать ничего из следующего (список включает только действия, относящиеся к моей проблеме):

  • Добавить или удалить виртуальные функции
  • Добавить или удалить переменные-члены
  • Изменить тип существующей переменной-члена
  • Изменить сигнатуру существующей функции

Я могу придумать два способа добавить эти данные в иерархию: добавление новой переменной-члена в корневой класс или добавление чисто виртуальных функций доступа ( чтобы данные можно было хранить в подклассах). Однако для обеспечения обратной совместимости я не могу сделать ни то, ни другое.

Библиотека широко использует идиому 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 m_mapNewData;      
};

class DerivedClass : public BaseClass
{
    void doSomething()
    {
        BaseClass::setNewData(this, new NewData());
    }
};

class Outside
{
   void doActions(BaseClass* action)
   {
       NewData* data = BaseClass::getNewData(action);
       ...
   }
};

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

Есть ли другие решения?

Спасибо.

10
задан linuxbuild 21 January 2011 в 13:41
поделиться