Alex Rivera | Logout

Pimpl idiom with inheritance

Asked 2009-01-29T11:44:29.100
20

I want to use pimpl idiom with inheritance.

Here is the base public class and its implementation class:

class A
{
    public:
      A(){pAImpl = new AImpl;};
      void foo(){pAImpl->foo();};
    private:
      AImpl* pAImpl;  
};
class AImpl
{
    public:
      void foo(){/*do something*/};
};

And I want to be able to create the derived public class with its implementation class:

class B : public A
{
    public:
      void bar(){pAImpl->bar();};    // Can't do! pAimpl is A's private.
};        

class BImpl : public AImpl
{
    public:
      void bar(){/*do something else*/};
};

But I can't use pAimpl in B because it is A's private.

So I see some ways to solve it:

  1. Create BImpl* pBImpl member in B, and pass it to A with additional A constructor, A(AImpl*).
  2. Change pAImpl to be protected (or add a Get function), and use it in B.
  3. B shouldn't inherit from A. Create BImpl* pBImpl member in B, and create foo() and bar() in B, that will use pBImpl.
  4. Any other way?

What should I choose?

Edit
Report

1 Answer

1

As stefan.ciobaca said, if you really wanted A to be extendable, you'd want pAImpl to be protected.

However, your definition in B of void bar(){pAImpl->bar();}; seems odd, as bar is a method on BImpl and not AImpl.

There are at least three easy alternatives that would avoid that issue:

  1. Your alternative (3).
  2. A variation on (3) in which BImpl extends AImpl (inheriting the existing implementation of foo rather than defining another), BImpl defines bar, and B uses its private BImpl* pBImpl to access both.
  3. Delegation, in which B holds private pointers to each of AImpl and BImpl and forwards each of foo and bar to the appropriate implementer.
answered 2009-01-29T13:18:47.240

Your Answer