views:

1213

answers:

2

I have three classes:

  1. A data holder class CDataHolder, which uses a Pimpl pattern

    class CDataHolder
    {
    public:
      // ...
    private:
    friend class CBase;
    struct PImpl;
    PImpl* iPimpl;
    };
    
  2. A base class CBase, which need to access the iPImpl member in CDataHolder, so it is a friend class of CDataHolder

    class CBase: 
    {
    protected:
    CDataHolder::Pimpl* getDataHolderPimpl();
    };
    
  3. A derived class CDerived from CBase, which need to access the same iPimpl member also. Here occurs a problem. The derived class cannot use the iPimpl member although its parent class is a friend class. like this:

    class CDerived : public CBase
    {
    public:
    void doSth() {
       CDataHolder::Pimpl *pImpl = getDataHolderPimpl(); // this line raises an error: 
                                                         // "illegal access from CDataHolder to protected/private member CDataHolder::PImpl"
    }
    };
    

    There are plenty of derived classes, so it's not a good way for each derived class to put a "friend class CDerivedXXX" line in CDataHolder class. How to overcome this issue? Is there a better way to do this? Thanks in advance.

+2  A: 

Since you have declared struct PImpl in the private part of CDataHolder class, only friends of CDataHolder can access the same. Why don't you put a forward declaration struct PImpl in the public section or even better before the CDataHolder class?

Abhay
Thank you and your quick reply. It works after putting "struct Pimpl" declaration to public. I misunderstood the error information given above, that means it cannot access the CDataHolder::Pimpl type. The type need a public access. Thank you very much.
douyw
+1  A: 

Friend is (rightfully) very limited and can't be inherited. I hate to beg the question, but maybe either A) you need public access to PImpl or some aspect of it, or B) you need the DataHolder class to do something with PImpl for you.

Robert