0

パラメータ化されたコンストラクタにPIMPL設計を使用するには?

/* ProcessImpl.h */
class ProcessImpl {
public :ProcessImpl(); 
    ProcessImpl(ProcessID thirdParty_pid);
    ~ProcessImpl();
} 

/* Process.h */
class Process { 
public:virtual ~Process () {}; 
    Process();
    Process(ProcessID thirdParty_pid);

protected: 
    void createImpl(); 
private: 
    ProcessImpl * _impl; 
}

/* Process.cpp */
Process::Process():_impl(NULL) {
}

Process::Process(ProcessID thirdParty_pid) {        
    createImpl();
    _impl->ProcessImpl(ldframework::ProcessID thirdParty_pid);
}

void Process::createImpl(){
    if(this->_impl == NULL) {
        this->_impl = new ProcessImpl();
    }
 }

これをコンパイルするとエラーが発生します: Process.cpp: エラー: クラス ProcessImpl の無効な使用
これはエラー _impl->ProcessImpl(ldframework::ProcessID thirdParty_pid) をスローする行です

Please help
4

2 に答える 2

1

あなたのコードは有効な C++ ではないので、実際の実装についての結論には飛びつかないので、最初から始めます。

クラスにパラメーター化されたコンストラクターがある場合、クラス メンバーと基底クラスを直接的または間接的に初期化するためにパラメーターが必要です。pimpl 化されたクラスには独自のデータ メンバーがないため (pimpl を除く)、コンストラクター パラメーターは実装クラスの初期化にのみ必要です。
pimpl イディオムの実装には 2 つの極端な例があります。

  1. すべてのロジックは実装クラスに入ります。外側のクラスは、すべての呼び出しを pimpl に転送する単なる馬鹿げたものです。
  2. ロジックは外側のクラスに残り、pimpl はデータのダム バンドルにすぎません。

もちろん、実際には、その間のすべてが可能です。

ケース 1 では、外部クラスのコンストラクターの署名は、実装クラスのコンストラクターの署名と同じである必要があり、任意の引数を pimpl コンストラクターに渡すだけです。

フー。

class Foo {
  struct FooImpl;
  std::unique_ptr<FooImpl> pImpl;
public:
  ~Foo();
  Foo(A const& a);
  Foo(B b, C* c, D& d);
};

Foo.cpp

struct Foo::FooImpl {
  FooImpl(A const& a);
  FooImpl(B b, C* c, D& d);
  /* Logic goes here */
};

Foo::~Foo() {} //defined here for correct deletion of the unique_ptr

Foo::Foo(A const& a)
  : pImpl(std::make_unique<FooImpl>(a))
{}

Foo::Foo(B b, C* c, D& d)
  : pImpl(std::make_unique<FooImpl>(std::move(b), c, d))
{}

一緒:

  1. クラスと pimpl-class に同じコンストラクタ シグネチャを使用します。各クラス コンストラクタは、対応する pimpl-constructor を呼び出すだけです。
  2. 参照またはポインターによって取得されるパラメーターは、そのまま pimpl コンストラクターに渡されます
  3. 値によって取得されるパラメーターは、pimpl コンストラクターに移動されます (転送)

これは、コンストラクター ロジックが完全に実装クラス内に実装される最も単純なソリューションです。

pimpl クラスが単なるデータのバンドルである別のケースでは、次のように、外部クラスのコンストラクター内にロジックが含まれます。

struct Foo::FooImpl {
  FooImpl(A const& a, B b, E e, F f);
  A a;
};

Foo::Foo(B b, C* c, D& d)
  : pImpl(std::make_unique<FooImpl>(A(), std::move(b), calcE(c,d), getSomeF())
{
  pImpl->a = someValueForA();
}

おわかりのように、コンストラクターを実装する戦略は、pimpl イディオムをまとめて実装する戦略に依存します。ロジックをpimplクラスに委任するか、メインクラスに残すかで、ある程度一貫していることを確認してください。

于 2013-07-26T07:57:00.200 に答える