Re: Partial pimpl design pattern?
In article
<559b868f-165e-407e-8001-9e01a575e8cd@v13g2000yqm.googlegroups.com>,
"jason.cipriani@gmail.com" <jason.cipriani@gmail.com> wrote:
On Dec 6, 4:33?pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
I'm writing a class where I want to keep a few details out of the
public header, but those details are only a small fraction of
everything in the class.
Normally I'd do this with pimpl or something, but I want to avoid the
inconvenience of coding and maintaining the entire pimpl abstraction.
I always get uncomfortable when I try a new design pattern though. My
question is: Is something like the example below in poor form? Is
there a better way?
So, say I originally have a class like this:
class MyClass {
public:
? MyClass ();
? ~MyClass ();
? void a ();
? void b ();
? void c ();
? void d ();
private:
? int x_;
? int y_;
};
And I only want to separate part of it. So I do this (I've inlined
function definitions to keep the example brief but note that, of
course, the actual source code is split into appropriate headers and
source files):
class MyClass {
public:
? MyClass () { impl_ = new MyClassPartialImpl(this); }
? ~MyClass () { delete impl_; }
? void a ();
? void b ();
? void c () { impl_->c(); }
? void d () { impl_->d(); }
private:
? int x_;
? friend MyClassPartialImpl;
? MyClassPartialImpl *impl_;
};
class MyClassPartialImpl {
public:
? explicit MyClassPartialImpl (MyClass *owner) : owner_(owner) { }
? ~MyClassPartialImpl ();
? void c ();
? void d ();
private:
? MyClass *owner_;
? int y_;
Stick a "friend MyClass;" here; both MyClass::a() and MyClass::b()
would have access to the "hidden" things in MyClassPartialImpl (e.g.
y_, or any private functions).
I wouldn't bother with friends:
class MyClass {
public:
MyClass();
~ MyClass();
MyClass(const MyClass& that); // note you need these
void operator=(MyClass that);
void c();
private:
int x;
struct Impl;
Impl* pimpl;
};
// in cpp file
struct MyClass::Impl
{
Impl():y(0) { }
int y;
};
MyClass(): x(0), pimpl(new Impl)
{
}
MyClass::~MyClass() {
delete pimpl;
}
MyClass::MyClass(const MyClass& that)
: x(that.x)
, pimpl( new Impl( *that.pimpl ) )
{
}
void MyClass::operator=(MyClass that)
{
x = that.x;
Impl* tmp = that.pimpl;
that.pimpl = pimpl;
pimpl = tmp;
}
void MyClass::c() {
pimpl->y = 4;
x = 8;
}