Search code examples
c++inheritancefriendprotectedaccess-control

Friendship vs inheritance


I've the class hierarchy below. Basically, I would like to establish a "has-a" relationship between the classes Foo and CComplexMat, i.e. class Foo "has-a" CComplexMat. From what I know, private and protected members of a class cannot be accessed from outside the class where they are defined.

However, there are two possibilities to allow other classes to access such members. The first one is to use friend classes. I could add a line friend class Foo<T>; in the declaration of class CComplexMat<T>, so that Foo<T> can access the protected and private members of class CComplexMat<T>.

The second possibility would be to use inheritance, which is the solution that I've chosen in the example. In this case, I'm considering a public inheritance so that both public and protected members of class CComplexMat<T> are accessible in class Foo<T>. However, the following error is shown:

error: ‘CMatrix<float>* CComplexMatrix<float>::m_pReal’ is protected

error: within this context

  1. I was wondering if somebody could shed some light on the bug?
  2. In which situations are "friendships" or "inheritances" more suitable?
template <class T>
class CMatrix{
    public:
     ...
        CMatrix<T> & operator = (const CMatrix<T> &);
        T & operator()(int, int, int);
        T operator()(int, int, int) const;
     ...
    private:
       T *** pData;
       int rows, cols, ch;
};

template <class T>
class CComplexMat: public CMatrix<T>{
    public:
    ...
    protected:
        CMatrix<T> *pReal;
        CMatrix<T> *pImag;
};

template <class T>
class Foo: public CComplexMat<T>{
    public:
        ...
        void doSomething(){
           ...
           CMatrix<T>*pTmp = pComplex->pReal; // error here.
           ...
        }
    ...
    private:
        CComplexMat<T> * pComplex;
    ...
};

Solution

  • Inheritance should only be used for "is-a" relationships. It looks to me like CComplexMat<T> has two CMatrix<T> members, but it's not the case that it "is-a" CMatrix<T>. Similar deal with Foo and CComplexMat<T>.

    So inheritance is almost certainly not the correct solution. That leaves:

    • Use friend to allow access between closely related classes.
    • Use public accessor methods to allow users of a class to "get at" private members in limited ways.

    For example, CComplexMat<T> should probably have private members for the real and imaginary parts but then also some accessors like:

    public:
        const CMatrix<T>& realPart() const;
        CMatrix<T>& realPart();
        const CMatrix<T>& imagPart() const;
        CMatrix<T>& imagPart();