Подтвердить что ты не робот

Когда использовать класс друга в С++

Возможный дубликат:
Когда вы должны использовать "друга" на С++?

Я расчесывал свой С++ (я разработчик Java), и я наткнулся на ключевое слово friend class, о котором я забыл некоторое время. Является ли это одной из тех функций, которые только часть кухонной раковины, или есть веская причина для этого, а не просто ванильный геттер? Я понимаю разницу в том, что он ограничивает доступ к данным, но я не могу придумать сценарий, когда это будет необходимо.

Примечание. Я видел подобный вопрос, но, в частности, я спрашиваю, это просто расширенная функция, которая не добавляет никакой реальной ценности, кроме как путать людей, которые смотрят на ваш код, пока они не поймут, что вы делаете?

4b9b3361

Ответ 1

Я согласен с комментариями, которые говорят, что ключевое слово friend может улучшить инкапсуляцию, если использовать мудро. Я бы добавил, что наиболее распространенное (законное!) Использование для классов друзей может быть проверено. Вы можете захотеть, чтобы класс тестера имел больший доступ, чем другие классы клиентов. Класс тестера может иметь веские основания для просмотра внутренних деталей, которые намеренно скрыты от других классов.

Ответ 2

По моему опыту, случаи, когда friend (или mutable, что немного похоже) фактически улучшают инкапсуляцию данных, редко встречаются по сравнению с тем, как часто он используется для разрыва инкапсуляции.

Это редко полезно для меня, но когда я использую его для случаев, когда мне пришлось разделить класс, который ранее был одним классом, на два отдельных класса, которым необходимо получить доступ к некоторым общим данным/функциям.

Отредактируйте ответ на комментарий программиста Outlaw: Мы абсолютно согласны с этим. Еще один вариант, помимо дружественных классов после их расщепления, заключается в том, чтобы создавать публичные аксессоры, которые иногда нарушают инкапсуляцию! Я думаю, что некоторые люди думают, что дружественные классы каким-то образом разрушают инкапсуляцию, потому что они видели, что она используется неправильно, и многие люди, вероятно, никогда не видят код, где он используется правильно, потому что это редкая вещь. Мне нравится ваш способ заявить об этом, хотя дружелюбие - хорошая промежуточная точка между тем, что вы не можете разделить свой класс и сделать ВСЕ доступным для публики.

Отредактируйте ответ на вопрос Дэвида Торнли: Я согласен с тем, что гибкость, которую С++ позволяет вам делать так, является результатом принятия проектных решений на С++. Я думаю, что это еще более важно для понимания того, что вообще является хорошим и плохим стилем в гибких языках. Перспектива Java заключается в том, что у вас никогда не должно быть классов друзей, чтобы они не предоставлялись, но, как программисты на C++, наша ответственность как сообщество заключается в определении надлежащего использования этих очень гибких, но иногда неправильно используемых языковых конструкций.

Изменить для ответа на Tom: Mutable не обязательно разрушает инкапсуляцию, но многие из использования изменяемого ключевого слова, которое я видел в реальных ситуациях, разрушают инкапсуляцию, потому что гораздо чаще встречаются люди, нарушающие инкапсуляцию с помощью изменяться, чем на самом деле находить и понимать правильное использование mutable в первую очередь.

Ответ 3

Если вы хотите, чтобы один класс (Factory) отвечал за создание экземпляров другого класса (Тип). Вы можете сделать конструктор типа private и, таким образом, убедиться, что только Factory может создавать объекты типа. Это полезно, когда вы хотите делегировать проверки другому классу, который может служить валидатором. Только один сценарий использования.

P.S. На самом деле отсутствует ключевое слово "friend" в С#...

Ответ 4

Конкретным экземпляром будет класс factory, где вы хотите, чтобы один класс создавался только через другой класс factory, поэтому вы делаете его закрытыми, а класс factory - другом созданного класса.

Это похоже на 2 "12-точечный 3/4" -дверный разъем - не очень распространенный, но когда вам это нужно, вы очень рад, что у вас есть это.

Ответ 6

Раздел часто задаваемых вопросов о друзьях: здесь

Раздел FQA о друзьях: здесь

Две разные точки зрения о друге.

Ответ 7

Я рассматриваю конструкцию friend как одну из тех функций языка, которые должны использоваться в редких случаях, но это не делает их бесполезными. Существует несколько шаблонов, которые требуют создания классов friend, многие из которых уже находятся на этом сайте в этой "Связанной" строке справа. ==== >

Ответ 8

Дружба используется, когда у вас есть несколько классов и/или функций, которые работают вместе, чтобы обеспечить ту же абстракцию или интерфейс. Классическим примером является реализация какого-то численного класса, и все несущественные операторные функции (*, -, +, < < и т.д.) Получают дружбу, так что они могут работать с частными данными численного класса.

Такие случаи использования несколько редки, но они существуют, а друг очень полезен.

Ответ 9

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

MyClass наследуется от GeneralClass. MyClass стал большим, поэтому вы создали HelperClass для инкапсуляции некоторых функций MyClass. Однако HelperClass нуждается в доступе к некоторым защищенным функциям в GeneralClass для правильной работы с ним, поэтому вы делаете HelperClass другом для MyClass.

Это лучше, чем просмотр защищенных функций, потому что они не должны быть доступны для всех, но это помогает сохранить ваш код в ООП, чтобы MyClass не слишком усложнялся. Это имеет смысл, потому что хотя HelperClass не имеет особого отношения к MyClass по наследству, у него есть какая-то логическая связь с ним, воплощенная в коде и в дизайне, как "друг".

Ответ 10

Я всегда (и только) использую друга для индивидуального тестирования частных методов. Единственный другой способ, который я могу себе представить, - загрузить публичный интерфейс со множеством методов тестирования, который слишком запутан, поэтому я предпочитаю скрывать методы тестирования в отдельном тестовом классе.

Что-то вроде этого:

class cMyClassTest;

class cMyClass
{
public:
.....

private:
friend cMyClassTest;
int calc();     // tricky algorithm, test carefully

};

class cMyClassTest
{
public:
int test_calc()
{
    cMyClass test;
    ....
    int result = test.calc();

    if( result == 42 )
        return 1;
    return 0;
}
};

Ответ 11

класс friend означает, что все мы знаем, что это значение переменной из другого класса, поэтому оно в основном используется для использования значений, поэтому нам не нужно возвращать значение другого класса в главную функцию, а затем основную функцию класса-члена, но он имеет проблему, которая является классом, является другом для другого класса, тогда класс friend должен находиться ниже этого класса