12

Pimpl's 是许多 C++ 代码中样板文件的来源。它们似乎是宏、模板和一些外部工具的组合可以解决的问题,但我不确定最简单的方法是什么。我已经看到模板可以帮助完成一些提升,但并不多——您最终仍然需要为您尝试包装的类的每个方法编写转发函数。有没有更简单的方法?

我在想象一个工具用作制作过程的一部分。您希望您的公共标头是 pimpl'd 类,因此您提供一些输入文件,例如 pimpl.in,其中列出了您想要包装的类(实现 un-pimpl'd),然后检查该文件,生成 pimpl 类,并且在“make install”期间仅安装它们的头文件(不是原始类的头文件)。问题是如果没有完整的 C++ 解析器,我看不到任何方法可以做到这一点,即使是编译器供应商也无法做到这一点。也许这些类可以以某种方式编写,使外部工具的工作更容易,但我确信我最终会错过各种极端情况(例如模板化类和/或模板化成员函数)。

有任何想法吗?有没有其他人已经为这个问题提供了解决方案?

4

3 回答 3

6

不,没有一个简单的答案。:-( 我认为几乎每个 OO 专家都说“更喜欢组合而不是继承”,会有语言支持使组合比继承容易得多。

于 2009-10-25T18:58:28.737 回答
2

我并不是说这很好(只是突然想到的东西)。
但是您可以尝试重载运算符 ->

#include <memory>
#include <iostream>

class X
{
    public:
    void plop()
    {
        std::cout << "Plop\n";
    }
};

class PimplX
{
    public:
        PimplX()
        {
            pimpl.reset(new X);
        }
        X* operator->()
        {
            return pimpl.get();
        }
    private:
        PimplX(PimplX const&);
        PimplX& operator=(PimplX const&);
        std::auto_ptr<X>    pimpl;
};   


int main()
{    
    PimplX      x;

    x->plop();
}
于 2009-10-25T23:49:34.267 回答
0

一种选择是改用接口类:

class ClassA {
  virtual void foo() = 0;
  static ClassA *create();
};

// in ClassA.cpp

class ImplA : public ClassA {
/* ... */
};
ClassA *ClassA::create() {
  return new ImplA();
}

然而,这确实增加了获取 vtable 函数指针的开销。

除此之外,我想不出任何这样的工具。正如您所说,解析 C++ 并非易事,并且还有其他语言不那么成问题(例如,C# 或 Java 后期绑定所有内容,因此您可以稍后更改它们的内存布局而不会出现问题)。

于 2009-10-25T18:19:09.943 回答