c++private-memberspimpl-idiomprivate-methods

How to access private member of impl class from original class using PIMPL approach


I am using the PIMPL approach and would like to access a private member of the implementation class from the regular class. Is there any legitimate way to do this? In the below code, there are two private members I would like to access. One of these is an attribute, the other is a method.

Here is my code:

Dave.h

#include "DaveImpl.h"

class Dave {
    public:
        Dave ();
        int getAge ();
    private:
        int getIq ();
        DaveImpl* _impl;
};

Dave.cc

 #include "Dave.h"

Dave::Dave () {
    _impl = new DaveImpl ();
}

int Dave::getAge () {
    return _impl->age;
}

int Dave::getIq () {
    return _impl->getIq ();
}

DaveImpl.h

class DaveImpl {
    public:
        DaveImpl ();
    private:
       int age;
       int iq;
       int getIq ();
};

DaveImpl.cc

#include "DaveImpl.h"

DaveImpl::DaveImpl () {
    age=60;
    iq=75;
}

int DaveImpl::getIq () {
    return iq;
}

When I compile the above code, I get the following messages:

Dave.cc:8:19: error: ‘int DaveImpl::age’ is private within this context
INFO: 1>     8 |     return _impl->age;
Dave.cc:12:26: error: ‘int DaveImpl::getIq()’ is private within this context
INFO: 1>    12 |     return _impl->getIq ();

Is there any way for me to access the "age" attribute or the "getIq" method in the above scenario ?

Note that I am stuck with the member and method in the implementation class being private. I cannot change that unfortunately.


Solution

  • You can declare getter in your impl class in public scope:

    class DaveImpl {
    public:
        DaveImpl ();
        int getAge() const {return age;} 
        int getIq() const {return iq;}
    private:
       int age;
       int iq;
    };
    

    and use them:

    int Dave::getAge () {
        return _impl->getAge();
    }
    
    int Dave::getIq () {
        return _impl->getIq ();
    }
    

    Also you can declare Dave class as a friend for your impl class, and Dave class will have an access to private fields of impl:

    class DaveImpl {
        friend class Dave;
        public:
            DaveImpl ();
        private:
           int age;
           int iq;
           int getIq ();
    };