Pimpl 的替代品

Alternative to Pimpl

我需要提供以下问题的解决方案:

A class 已作为图书馆发布并可供全世界使用。它的设计方式不使用 pimpl 方法。 class 中需要定义两个新的数据成员。如何在不破坏 ABI 的情况下将这些额外的数据成员添加到 class?解决方案应该是一种通用方法,可用于避免任何 class 设计的 ABI 损坏,它不使用 pimpl 方法。

我的第一个解决方案是创建一个新的 class 继承自之前的 class,然后在其中添加 2 个新成员。然后需要这 2 个新数据成员的源代码可以使用这个新创建的 class。但是,我的解决方案被标记为不正确。有人告诉我,我必须以与 pimpl 类似的方法将现有数据成员重新用于其他目的。我不明白这到底是什么意思,因为我没有得到这个现有 class.

的任何接口

pimpl 有哪些替代方案可以在不破坏 ABI 的情况下更改现有 classes?

我的猜测如下。

假设您的 class 包含一个指针数据成员,例如 char* x(类型不重要),用于与您计划的扩展无关的事情。您的教授希望您将 x 解释为指向另一事物的指针:

struct expansion {
    char* newX;
    int newDataMember1;
    double newDataMember2;
};

现在,每当您在旧代码中看到 x 时,将其替换为对成员函数的调用 getX():

private:
  char*& getX() {
    return ((expansion*)x)->newX;
  }

您应该在构造函数中初始化 x

  x = (char*)new expansion; // or
  MyClass() : x((char*)new expansion)

并在析构函数中释放它。

现在你有了旧的 x 作为 getX() 和新的数据成员(编写一个明显的成员函数来访问它们)。

当然,您永远不应该在任何实际代码中做任何类似的事情,这就是为什么我不讨论智能指针、异常安全、新样式转换和其他可以远程认为是高级或良好样式的东西。添加这些来调味。这不是编写生产代码的方法,而是纯粹让教授满意的练习。

如果您的 class 中没有指针成员怎么办?在这种情况下,您将不得不打破一些实际的 C++ 规则(除了良好软件设计的原则,这些原则在您甚至开始考虑这个“解决方案”的那一刻就付诸东流了)。改用一些不可或缺的成员(注意,C++ 标准并不保证它会工作,但对于大多数实现来说,只要你的成员的大小至少是指针的大小就可以了)。或者重新利用 多个 彼此相邻的成员(使用 reinterpret_cast 或放置 new 将指针放置在那里)。或者,如果你的 class 有一个 vector 的东西,使用向量管理的数据来存储一个指针,再次使用转换或放置 new hack。一切顺利......当然,只要你得到教授的批准,C++ 标准就该死了。