Почему я не могу объявить друга в одном классе, который является частным членом другого класса? - PullRequest
3 голосов
/ 21 июля 2010

С учетом следующего кода:

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;
}

Почему класс Screen не может объявить функцию-член WindowMgr::relocateScreen как друга? Screen не хочет использовать эту приватную функцию-член другого класса, а просто хочет, чтобы эта функция могла иметь доступ к своим собственным приватным членам.

Публикация функции relocateScreen может быть плохим дизайном, если она предназначена только для использования в классе WindowMgr. Точно так же, сделать Screen другом WindowMgr может быть плохим дизайном, если он не намерен обращаться к закрытым членам WindowMgr в любом другом случае.

Где я здесь не так? Какой правильный подход? Я себя дурачу?

Ответы [ 4 ]

1 голос
/ 22 июля 2010

Объявление друга не работает, потому что WindowMgr::relocateScreen() является приватным для WindowMgr.

C ++ стандарт 11.4-7:

"Имя, назначенное другом декларация должна быть доступна в область действия класса, содержащего декларация друга ... "

Лично я бы сделал relocateScreen() закрытой функцией-членом Screen и сделал бы WindowMgr a friend из Screen. Таким образом, WindowMgr может просто позвонить relocateScreen() на Screen и ему не нужно будет трогать ни одного из членов данных Screen.

0 голосов
/ 22 июля 2010

В Silico - Хороший для цитирования стандарта.Спя на нем, я теперь вижу обоснование:

Объявляя WindowMgr::relocateScreen со своим списком параметров в качестве друга в Screen, класс Screen становится зависимым от частной реализации WindowMgrучебный класс.Это нарушает инкапсуляцию / сокрытие информации.

Чтобы не нарушать принципы OOD, только открытые функции-члены класса могут быть объявлены как друзья в другом, потому что в противном случае последний становится зависимым от частной реализациибывший.

0 голосов
/ 22 июля 2010

Почему бы не выделить WindowMgr :: relocateScreen в другой класс, скажем WindowMgrFoo с функцией 1 relocateScreen.Delcare WindowMgrFoo - друг Screen in Screen, и WindowMgr унаследовал его от WindowMgrFoo?Или просто у WindowMgr есть ссылка на WindowMgrFoo, но вам нужно изменить способ его вызова пользователями, если вы сделаете его публичным.

0 голосов
/ 22 июля 2010

WindowMgr должен объявить Screen как друга. Вы можете использовать предварительную декларацию.

...