C++ クラスの実装を自動化する — 簡単な方法はありますか?
-
06-07-2019 - |
質問
Pimpl は、多くの C++ コードにおける定型文のソースです。これらはマクロ、テンプレート、そしておそらく小さな外部ツールの組み合わせで解決できそうな問題のように思えますが、最も簡単な方法が何かはわかりません。 テンプレを見てきました これは一部の改良には役立ちますが、それほど多くはありません。ラップしようとしているクラスのメソッドごとに転送関数を記述する必要があります。もっと簡単な方法はありますか?
作成プロセスの一部として使用されるツールを想像しています。パブリックヘッダーを pimpl 化したクラスにしたい場合は、ラップしたいクラス (pimpl 化されていない実装) をリストした入力ファイル (pimpl.in など) を指定すると、そのファイルが検査されます。 pimpl クラスが生成され、そのヘッダーのみ (元のクラスのヘッダーではない) が「make install」中にインストールされます。問題は、本格的な C++ パーサーなしではこれを行う方法が見つからないことです。これはコンパイラー ベンダーですら正しく理解できないことです。おそらく、外部ツールの作業を容易にする何らかの方法でクラスを作成できるかもしれませんが、最終的にはあらゆる種類の特殊なケース (例:テンプレート化されたクラスおよび/またはテンプレート化されたメンバー関数)。
何か案は?この問題の解決策をすでに考え出した人はいますか?
解決
いいえ、簡単な答えはありません。 :-(ほぼすべてのOOエキスパートが「継承よりも合成を優先する」と言っていると思いますが、継承よりも合成をずっと簡単にするための言語サポートがあるでしょう。
他のヒント
これが良いと言っているわけではありません(ただ思いついただけです)。
ただし、演算子をオーバーロードして実験することはできます ->
#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();
}
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のすべてが遅延バインドされるため、メモリ内のレイアウトを後で問題なく変更できます)。