12

Pimpl は、多くの C++ コードのボイラープレートのソースです。それらは、マクロ、テンプレート、およびおそらく外部ツールの助けを少し組み合わせることで解決できるようなものに思えますが、最も簡単な方法が何であるかはわかりません. 持ち上げるのに役立つテンプレートを見てきましたが、それほど多くはありません。ラップしようとしているクラスのすべてのメソッドに対して転送関数を記述する必要があります。もっと簡単な方法はありますか?

make プロセスの一部として使用されるツールを想像しています。パブリックヘッダーを pimpl 化されたクラスにしたいので、ラップしたいクラス (pimpl 化されていない実装済み) をリストする pimpl.in などの入力ファイルを提供すると、そのファイルが調べられます。 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

1 つのオプションは、代わりにインターフェイス クラスを使用することです。

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 に答える