如何将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
答案 0 :(得分:1)
由于您的代码无效C ++,我不会对您的实际实现做出结论,因此我将从头开始:
如果类具有参数化构造函数,则需要参数来直接或间接初始化类成员和基类。由于pimpl'd类没有自己的数据成员(pimpl除外),因此仅需要初始化实现类的构造函数参数。
pimpl习语的实现有两个极端:
当然,在实践中,两者之间的任何事情都是可能的。
在case 1中,外部类的构造函数签名应该与实现类'构造函数的签名相同,并且只是将任何参数传递给pimpl构造函数:
<强> foo.h中强>
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))
{}
合:
这是最简单的解决方案,其中构造函数逻辑完全在实现类中实现。
在另一种情况下,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类或将其保留在主类中时,您都会保持一致。
答案 1 :(得分:0)
只需在构造函数中构造pimpl。
请注意,您还应该实现复制构造函数和赋值运算符,因为复制对象将导致两个副本被销毁时出现未定义的行为。
理想情况下,pimpl应始终有效以避免检查它是否始终有效,但是按照您的代码,您可能会有以下内容:
class Process {
public:
virtual ~Process () {
};
Process() {
// Ideally the impl_ pointer should be intialized to avoid
// having to check it in every function that uses it..
}
Process(ProcessID pid) {
impl_.reset(new ProcessImpl(pid));
}
Process(Process const& rhs) {
if (rhs.impl_.get()) {
impl_.reset(new ProcessImpl(*rhs.impl_));
}
}
Process& operator=(Process const& rhs) {
if (this != &rhs) {
if (rhs.impl_.get()) {
impl_.reset(new ProcessImpl(*rhs.impl_));
}
else {
impl_.reset();
}
}
return *this;
}
private:
std::unique_ptr<ProcessImpl> impl_;
};