扩展类并保持二进制向后兼容性

use*_*511 10 c++ api-design backwards-compatibility

我正在尝试向现有库添加新功能.我需要将新数据添加到类层次结构中,以便根类具有访问器.任何人都应该能够获得这些数据,只有子类可以设置它(即公共getter和受保护的setter).

为了保持向后兼容性,我知道我不能执行以下任何操作(列表仅包括与我的问题相关的操作):

  • 添加或删除虚拟功能
  • 添加或删除成员变量
  • 更改现有成员变量的类型
  • 更改现有功能的签名

我可以想到将这些数据添加到层次结构的两种方法:向根类添加新的成员变量或添加纯虚拟访问器函数(以便可以将数据存储在子类中).但是,为了保持向后的可比性,我不能做其中任何一个.

该库正在广泛使用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);
       ...
   }
};
Run Code Online (Sandbox Code Playgroud)

现在,虽然这个解决方案可能有用,但我发现它非常难看(当然我也可以添加非静态访问器函数,但这不会消除丑陋).

还有其他解决方案吗?

谢谢.

Bjö*_*lex 3

您可以使用装饰器模式。装饰器可以公开新的数据元素,并且不需要对现有类进行任何更改。如果客户通过工厂获取他们的对象,这种方法效果最好,因为这样你就可以透明地添加装饰器。