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

标签 c++ backwards-compatibility api-design

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

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

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

我可以想到两种方法将此数据添加到层次结构中:将新成员变量添加到根类或添加纯虚拟访问函数(以便数据可以存储在子类中)。但是,为了保持向后兼容性,我不能执行任何一项操作。

图书馆正在广泛使用 pimpl习语,但不幸的是,我必须修改的根类使用这个习语。然而,子类使用这个习惯用法。

现在我能想到的唯一解决方案是用静态 HashMap 模拟成员变量。所以我可以创建一个静态散列映射,将这个新成员存储到其中,并为其实现静态访问​​器。像这样的东西(在伪 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);
       ...
   }
};

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

还有其他解决办法吗?

谢谢。

最佳答案

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

关于c++ - 扩展类并保持二进制向后兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4459504/

相关文章:

iPhone - 如何确定现有项目的部署目标 iOS 版本

java - 返回 Try 的方法是否允许抛出异常?

rest - 如何指示 REST API 端点已删除

c++ - 如何将 OpenCV 的输出显示或流式传输到 HTML 页面或其他一些客户端应用程序

c# - 在 Visual Studio 中通过 C# 类编译 C++ 代码

c# - 处理 API 版本控制 .NET Core 中的代码重复

Restful 设计 : when to use sub-resources?

c++ - 如何在 C++ 中将空格和换行符分隔的整数读入二维数组?

c++ - Unicode、字符指针和 wcslen

c# - 当外部库不向后兼容时检查属性是否存在