2010-07-21 2 views
3

Учитывая следующий код:Почему я не могу объявить друга в одном классе, который является частным членом другого класса?

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 в любом другом случае.

В каком месте я ошибаюсь? Каков правильный подход? Неужели я обманываю себя?

ответ

1

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

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

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

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

0

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

+0

Передовая декларация уже существует. На самом деле, если бы я сделал класс Screen другом в WindowMgr, объявление класса Screen будет введено в окружающую область, явно удалив необходимость в прямом объявлении. – James

0

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

0

В Silico - Ницца для цитирования стандарта. После спал на ней теперь я вижу обоснование:

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

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

Смежные вопросы