views:

72

answers:

4

Given the following code:

class Screen;

class WindowMgr
{
    WindowMgr& relocateScreen( int r, int c, Screen& s);
};

class Screen
{
    friend WindowMgr& WindowMgr::relocateScreen( int r, int c, Screen& s);
    // ^ cannot access private member declared in class 'WindowMgr'

    int m_nR,
        m_nC;
};

WindowMgr& WindowMgr::relocateScreen( int r, int c, Screen& s)
{
    s.m_nR = r;
    s.m_nC = c;
    return *this;
}

Why can the Screen class not declare the WindowMgr::relocateScreen member function as a friend? Screen is not wanting to use this private member-function of another class, but simply wants that function to be able access its own private members.

Making the relocateScreen function public might be bad design if it's intented only for use within the WindowMgr class. Equally, making Screen a friend of WindowMgr might be bad design if it is not intented to access private members of WindowMgr in any other case.

Where am I going wrong here? What is the correct approach? Am I making a fool of myself?

A: 

The WindowMgr will have to declare Screen as a friend. You can use a forward declaration.

DeadMG
The forward declaration is already there. In fact if I made class Screen a friend in WindowMgr, the declaration of class Screen would be introduced into the surrounding scope, explicitly removing the need for the forward declaration.
James
A: 

The friend declaration doesn't work because WindowMgr::relocateScreen() is private to WindowMgr.

C++ standard 11.4-7:

"A name nominated by a friend declaration shall be accessible in the scope of the class containing the friend declaration..."

Personally, I would make relocateScreen() a private member function of Screen and make WindowMgr a friend of Screen. That way, WindowMgr can just call relocateScreen() on Screen and won't have to touch any of the data members of Screen.

In silico
A: 

Why not factor the WindowMgr::relocateScreen out into a different class, say WindowMgrFoo witht the 1 relocateScreen function. Delcare WindowMgrFoo a friend of Screen in Screen and have WindowMgr inherit privately from WindowMgrFoo? Or just have WindowMgr have a reference to a WindowMgrFoo, but that you need to change how it's called by users if you make it public.

frankc
A: 

In Silico - Nice one for citing the standard. Having slept on it I now see the rationale:

By declaring WindowMgr::relocateScreen with its paramater list to be a friend in Screen, the Screen class becomes dependent on the private implementation of the WindowMgr class. This violates encapsulation/information hiding.

In order to not violate the tenets of OOD, only public member-functions of class can be declared as friends in another, because otherwise the latter becomes dependent on the private implementation of the former.

James